From ff806b239e6fb542ef1c9a5feb7cfad229a433df Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 20 Apr 2024 08:31:33 -0300 Subject: [PATCH 1/9] 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 2/9] 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 3/9] 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 4/9] 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 5/9] [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 6/9] 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 7/9] 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 8/9] 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 9/9] [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):