Merge pull request #11901 from Pierre-Sassoulas/migrate-from-isort-to-ruff
Migrate from ``autoflake``, ``black``, ``isort``, ``pyupgrade``, ``flake8`` and ``pydocstyle``, to ``ruff``
This commit is contained in:
		
						commit
						bdfc5c80d8
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
-   repo: https://github.com/adamchainz/blacken-docs
 | 
			
		||||
    rev: 1.16.0
 | 
			
		||||
    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
 | 
			
		||||
    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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import sys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    import cProfile
 | 
			
		||||
    import pstats
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SKIP = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
from unittest import TestCase  # noqa: F401
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for i in range(15000):
 | 
			
		||||
    exec(
 | 
			
		||||
        f"""
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ from typing import TYPE_CHECKING
 | 
			
		|||
 | 
			
		||||
from _pytest import __version__ as version
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    import sphinx.application
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ import os.path
 | 
			
		|||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
mydir = os.path.dirname(__file__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
import os.path
 | 
			
		||||
import shutil
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py")
 | 
			
		||||
pytest_plugins = ("pytester",)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import textwrap
 | 
			
		|||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pythonlist = ["python3.9", "python3.10", "python3.11"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,14 +33,12 @@ class Python:
 | 
			
		|||
        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 @@ class Python:
 | 
			
		|||
        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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
xfail = pytest.mark.xfail
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ from pathlib import Path
 | 
			
		|||
 | 
			
		||||
import requests
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,9 +8,9 @@ our CHANGELOG) into Markdown (which is required by GitHub Releases).
 | 
			
		|||
 | 
			
		||||
Requires Python3.6+.
 | 
			
		||||
"""
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from typing import Sequence
 | 
			
		||||
 | 
			
		||||
import pypandoc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,8 +14,8 @@ After that, it will create a release using the `release` tox environment, and pu
 | 
			
		|||
`pytest bot <pytestbot@gmail.com>` 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
# mypy: disallow-untyped-defs
 | 
			
		||||
import sys
 | 
			
		||||
from subprocess import call
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main() -> int:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,13 +11,14 @@ from typing import TypedDict
 | 
			
		|||
 | 
			
		||||
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 iter_plugins() -> Iterator[PluginInfo]:
 | 
			
		|||
 | 
			
		||||
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"""
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,9 +63,9 @@ If things do not work right away:
 | 
			
		|||
"""
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ from .code import TracebackEntry
 | 
			
		|||
from .source import getrawcode
 | 
			
		||||
from .source import Source
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = [
 | 
			
		||||
    "Code",
 | 
			
		||||
    "ExceptionInfo",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.deprecated import check_ispytest
 | 
			
		|||
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 @@ class TracebackEntry:
 | 
			
		|||
 | 
			
		||||
        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 @@ class Traceback(List[TracebackEntry]):
 | 
			
		|||
        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 @@ class ExceptionInfo(Generic[E]):
 | 
			
		|||
 | 
			
		||||
        .. 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 @@ class ExceptionInfo(Generic[E]):
 | 
			
		|||
    def __repr__(self) -> str:
 | 
			
		||||
        if self._excinfo is None:
 | 
			
		||||
            return "<ExceptionInfo for raises contextmanager>"
 | 
			
		||||
        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 @@ class FormattedExcinfo:
 | 
			
		|||
            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 @@ class FormattedExcinfo:
 | 
			
		|||
                # 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 @@ class ReprEntry(TerminalRepr):
 | 
			
		|||
        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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 Optional
 | 
			
		|||
from typing import overload
 | 
			
		||||
from typing import Tuple
 | 
			
		||||
from typing import Union
 | 
			
		||||
import warnings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Source:
 | 
			
		||||
| 
						 | 
				
			
			@ -47,10 +47,12 @@ class Source:
 | 
			
		|||
    __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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
from .terminalwriter import get_terminal_width
 | 
			
		||||
from .terminalwriter import TerminalWriter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = [
 | 
			
		||||
    "TerminalWriter",
 | 
			
		||||
    "get_terminal_width",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ from typing import TextIO
 | 
			
		|||
 | 
			
		||||
from .wcwidth import wcswidth
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# This code was initially copied from py 1.8.1, file _io/terminalwriter.py.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -183,9 +184,7 @@ class TerminalWriter:
 | 
			
		|||
        """
 | 
			
		||||
        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 @@ class TerminalWriter:
 | 
			
		|||
                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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
import unicodedata
 | 
			
		||||
from functools import lru_cache
 | 
			
		||||
import unicodedata
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@lru_cache(100)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ from typing import Callable
 | 
			
		|||
from typing import TYPE_CHECKING
 | 
			
		||||
from typing import TypeVar
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from typing_extensions import ParamSpec
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 isdir
 | 
			
		|||
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 @@ class LocalPath:
 | 
			
		|||
        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 @@ class LocalPath:
 | 
			
		|||
            #   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 @@ class LocalPath:
 | 
			
		|||
 | 
			
		||||
        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 @@ class LocalPath:
 | 
			
		|||
            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 @@ class LocalPath:
 | 
			
		|||
        # 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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ from _pytest.config import hookimpl
 | 
			
		|||
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]:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 io
 | 
			
		|||
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 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
 | 
			
		||||
| 
						 | 
				
			
			@ -671,9 +672,9 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
			
		|||
            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 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
			
		|||
                    ]
 | 
			
		||||
                ):
 | 
			
		||||
                    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 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
			
		|||
            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 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
			
		|||
            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 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
			
		|||
        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 @@ class AssertionRewriter(ast.NodeVisitor):
 | 
			
		|||
                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})"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ from _pytest.assertion import util
 | 
			
		|||
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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,13 +15,14 @@ from typing import Protocol
 | 
			
		|||
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]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,7 @@ from _pytest.nodes import Directory
 | 
			
		|||
from _pytest.nodes import File
 | 
			
		||||
from _pytest.reports import TestReport
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
README_CONTENT = """\
 | 
			
		||||
# pytest cache directory #
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -368,15 +369,13 @@ class LFPlugin:
 | 
			
		|||
 | 
			
		||||
                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":
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,9 +4,9 @@ import abc
 | 
			
		|||
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 File
 | 
			
		|||
from _pytest.nodes import Item
 | 
			
		||||
from _pytest.reports import CollectReport
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -790,9 +791,7 @@ class CaptureManager:
 | 
			
		|||
            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] <pytest.CaptureFixture>`.
 | 
			
		||||
 | 
			
		||||
    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] <pytest.CaptureFixture>`.
 | 
			
		||||
 | 
			
		||||
    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] <pytest.CaptureFixture>`.
 | 
			
		||||
 | 
			
		||||
    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] <pytest.CaptureFixture>`.
 | 
			
		||||
 | 
			
		||||
    Example:
 | 
			
		||||
 | 
			
		||||
    .. code-block:: python
 | 
			
		||||
 | 
			
		||||
        def test_system_echo(capfdbinary):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,17 +6,18 @@ import dataclasses
 | 
			
		|||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,18 +5,17 @@ import collections.abc
 | 
			
		|||
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 Tuple
 | 
			
		|||
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 HookspecMarker
 | 
			
		|||
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.stash import Stash
 | 
			
		|||
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 @@ class PytestPluginManager(PluginManager):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
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 @@ class Config:
 | 
			
		|||
 | 
			
		||||
            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 @@ class Config:
 | 
			
		|||
                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 @@ class Config:
 | 
			
		|||
        can be used to explicitly use the global verbosity level.
 | 
			
		||||
 | 
			
		||||
        Example:
 | 
			
		||||
 | 
			
		||||
        .. code-block:: ini
 | 
			
		||||
 | 
			
		||||
            # content of pytest.ini
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 @@ import _pytest._io
 | 
			
		|||
from _pytest.config.exceptions import UsageError
 | 
			
		||||
from _pytest.deprecated import check_ispytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FILE_OR_DIR = "file_or_dir"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +217,7 @@ class Parser:
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
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 @@ class MyOptionParser(argparse.ArgumentParser):
 | 
			
		|||
        ) -> 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]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,6 @@ import argparse
 | 
			
		|||
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 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
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +26,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
 | 
			
		||||
| 
						 | 
				
			
			@ -264,8 +265,7 @@ class pytestPDB:
 | 
			
		|||
                    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}")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ from _pytest.warning_types import PytestDeprecationWarning
 | 
			
		|||
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 = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 Tuple
 | 
			
		|||
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 import Module
 | 
			
		|||
from _pytest.python_api import approx
 | 
			
		||||
from _pytest.warning_types import PytestWarning
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    import doctest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -486,9 +487,9 @@ def _patch_unwrap_mock_aware() -> Generator[None, None, None]:
 | 
			
		|||
            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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,11 +2,12 @@ import os
 | 
			
		|||
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]()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 Tuple
 | 
			
		|||
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 _ScopeName
 | 
			
		|||
from _pytest.scope import HIGH_SCOPES
 | 
			
		||||
from _pytest.scope import Scope
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from typing import Deque
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -601,13 +602,9 @@ class FixtureRequest(abc.ABC):
 | 
			
		|||
            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 @@ class SubRequest(FixtureRequest):
 | 
			
		|||
        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 @@ class FixtureLookupError(LookupError):
 | 
			
		|||
                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 @@ class FixtureDef(Generic[FixtureValue]):
 | 
			
		|||
        return request.param_index if not hasattr(request, "param") else request.param
 | 
			
		||||
 | 
			
		||||
    def __repr__(self) -> str:
 | 
			
		||||
        return "<FixtureDef argname={!r} scope={!r} baseid={!r}>".format(
 | 
			
		||||
            self.argname, self.scope, self.baseid
 | 
			
		||||
        )
 | 
			
		||||
        return f"<FixtureDef argname={self.argname!r} scope={self.scope!r} baseid={self.baseid!r}>"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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 @@ class FixtureFunctionMarker:
 | 
			
		|||
        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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 pytest_cmdline_parse() -> Generator[None, Config, Config]:
 | 
			
		|||
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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,11 @@ from typing import Union
 | 
			
		|||
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,12 +7,11 @@ Based on initial code from Ross Lawley.
 | 
			
		|||
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 Match
 | 
			
		|||
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.fixtures import FixtureRequest
 | 
			
		|||
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 record_testsuite_property(request: FixtureRequest) -> Callable[[str, object]
 | 
			
		|||
        `pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
 | 
			
		||||
        :issue:`7767` for details.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    __tracebackhide__ = True
 | 
			
		||||
 | 
			
		||||
    def record_func(name: str, value: object) -> None:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.pytester import RunResult
 | 
			
		|||
from _pytest.terminal import TerminalReporter
 | 
			
		||||
from _pytest.tmpdir import TempPathFactory
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    import pexpect
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.main import Session
 | 
			
		|||
from _pytest.stash import StashKey
 | 
			
		||||
from _pytest.terminal import TerminalReporter
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    logging_StreamHandler = logging.StreamHandler[StringIO]
 | 
			
		||||
else:
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +117,6 @@ class ColoredLevelFormatter(DatetimeFormatter):
 | 
			
		|||
        .. 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 @@ class PercentStyleMultiline(logging.PercentStyle):
 | 
			
		|||
            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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,8 @@ import fnmatch
 | 
			
		|||
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 overload
 | 
			
		|||
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 @@ class Session(nodes.Collector):
 | 
			
		|||
    @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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ from _pytest.config import UsageError
 | 
			
		|||
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}"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ from typing import NoReturn
 | 
			
		|||
from typing import Optional
 | 
			
		||||
from typing import Sequence
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = [
 | 
			
		||||
    "Expression",
 | 
			
		||||
    "ParseError",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		|||
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.deprecated import MARKED_FIXTURE
 | 
			
		|||
from _pytest.outcomes import fail
 | 
			
		||||
from _pytest.warning_types import PytestUnknownMarkWarning
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from ..nodes import Node
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +113,6 @@ class ParameterSet(NamedTuple):
 | 
			
		|||
            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 @@ if TYPE_CHECKING:
 | 
			
		|||
 | 
			
		||||
    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 @@ if TYPE_CHECKING:
 | 
			
		|||
            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 @@ if TYPE_CHECKING:
 | 
			
		|||
                None, Type[BaseException], Tuple[Type[BaseException], ...]
 | 
			
		||||
            ] = ...,
 | 
			
		||||
            strict: bool = ...,
 | 
			
		||||
        ) -> MarkDecorator: ...
 | 
			
		||||
        ) -> MarkDecorator:
 | 
			
		||||
            ...
 | 
			
		||||
 | 
			
		||||
    class _ParametrizeMarkDecorator(MarkDecorator):
 | 
			
		||||
        def __call__(  # type: ignore[override]
 | 
			
		||||
| 
						 | 
				
			
			@ -478,7 +483,8 @@ if TYPE_CHECKING:
 | 
			
		|||
                ]
 | 
			
		||||
            ] = ...,
 | 
			
		||||
            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``.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 overload
 | 
			
		|||
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 @@ class MonkeyPatch:
 | 
			
		|||
        which undoes any patching done inside the ``with`` block upon exit.
 | 
			
		||||
 | 
			
		||||
        Example:
 | 
			
		||||
 | 
			
		||||
        .. code-block:: python
 | 
			
		||||
 | 
			
		||||
            import functools
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +167,8 @@ class MonkeyPatch:
 | 
			
		|||
        name: object,
 | 
			
		||||
        value: Notset = ...,
 | 
			
		||||
        raising: bool = ...,
 | 
			
		||||
    ) -> None: ...
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        ...
 | 
			
		||||
 | 
			
		||||
    @overload
 | 
			
		||||
    def setattr(
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +177,8 @@ class MonkeyPatch:
 | 
			
		|||
        name: str,
 | 
			
		||||
        value: object,
 | 
			
		||||
        raising: bool = ...,
 | 
			
		||||
    ) -> None: ...
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        ...
 | 
			
		||||
 | 
			
		||||
    def setattr(
 | 
			
		||||
        self,
 | 
			
		||||
| 
						 | 
				
			
			@ -320,10 +320,8 @@ class MonkeyPatch:
 | 
			
		|||
        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 @@ class MonkeyPatch:
 | 
			
		|||
 | 
			
		||||
    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))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		|||
from typing import TYPE_CHECKING
 | 
			
		||||
from typing import TypeVar
 | 
			
		||||
from typing import Union
 | 
			
		||||
import warnings
 | 
			
		||||
 | 
			
		||||
import pluggy
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +39,7 @@ from _pytest.pathlib import commonpath
 | 
			
		|||
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 @@ class Node(abc.ABC, metaclass=NodeMeta):
 | 
			
		|||
        # 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 @@ class Node(abc.ABC, metaclass=NodeMeta):
 | 
			
		|||
                    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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]]()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 os.path import sep
 | 
			
		|||
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 Tuple
 | 
			
		|||
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"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,19 +5,19 @@ PYTEST_DONT_REWRITE
 | 
			
		|||
"""
 | 
			
		||||
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.reports import TestReport
 | 
			
		|||
from _pytest.tmpdir import TempPathFactory
 | 
			
		||||
from _pytest.warning_types import PytestWarning
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    import pexpect
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +188,7 @@ class LsofFdLeakChecker:
 | 
			
		|||
                    "*** 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 @@ class RecordedHookCall:
 | 
			
		|||
 | 
			
		||||
    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 @@ class HookRecorder:
 | 
			
		|||
    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 @@ class HookRecorder:
 | 
			
		|||
            "pytest_collectreport",
 | 
			
		||||
            "pytest_runtest_logreport",
 | 
			
		||||
        ),
 | 
			
		||||
    ) -> Sequence[Union[CollectReport, TestReport]]: ...
 | 
			
		||||
    ) -> Sequence[Union[CollectReport, TestReport]]:
 | 
			
		||||
        ...
 | 
			
		||||
 | 
			
		||||
    def getreports(
 | 
			
		||||
        self,
 | 
			
		||||
| 
						 | 
				
			
			@ -372,14 +377,12 @@ class HookRecorder:
 | 
			
		|||
                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 @@ class HookRecorder:
 | 
			
		|||
    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 @@ class HookRecorder:
 | 
			
		|||
            "pytest_collectreport",
 | 
			
		||||
            "pytest_runtest_logreport",
 | 
			
		||||
        ),
 | 
			
		||||
    ) -> Sequence[Union[CollectReport, TestReport]]: ...
 | 
			
		||||
    ) -> Sequence[Union[CollectReport, TestReport]]:
 | 
			
		||||
        ...
 | 
			
		||||
 | 
			
		||||
    def getfailures(
 | 
			
		||||
        self,
 | 
			
		||||
| 
						 | 
				
			
			@ -801,7 +807,6 @@ class Pytester:
 | 
			
		|||
            The first created file.
 | 
			
		||||
 | 
			
		||||
        Examples:
 | 
			
		||||
 | 
			
		||||
        .. code-block:: python
 | 
			
		||||
 | 
			
		||||
            pytester.makefile(".txt", "line1", "line2")
 | 
			
		||||
| 
						 | 
				
			
			@ -855,7 +860,6 @@ class Pytester:
 | 
			
		|||
        existing files.
 | 
			
		||||
 | 
			
		||||
        Examples:
 | 
			
		||||
 | 
			
		||||
        .. code-block:: python
 | 
			
		||||
 | 
			
		||||
            def test_something(pytester):
 | 
			
		||||
| 
						 | 
				
			
			@ -875,7 +879,6 @@ class Pytester:
 | 
			
		|||
        existing files.
 | 
			
		||||
 | 
			
		||||
        Examples:
 | 
			
		||||
 | 
			
		||||
        .. code-block:: python
 | 
			
		||||
 | 
			
		||||
            def test_something(pytester):
 | 
			
		||||
| 
						 | 
				
			
			@ -1265,9 +1268,7 @@ class Pytester:
 | 
			
		|||
        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 @@ class Pytester:
 | 
			
		|||
            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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 Sequence
 | 
			
		|||
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 PytestCollectionWarning
 | 
			
		|||
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 @@ class Class(PyCollector):
 | 
			
		|||
            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 @@ class Class(PyCollector):
 | 
			
		|||
            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 @@ class Metafunc:
 | 
			
		|||
            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 @@ class Metafunc:
 | 
			
		|||
            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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 @@ import _pytest._code
 | 
			
		|||
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 @@ class ApproxSequenceLike(ApproxBase):
 | 
			
		|||
        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 <https://peps.python.org/pep-0678/>`__ ``__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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 Tuple
 | 
			
		|||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 Collector
 | 
			
		|||
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 @@ class BaseReport:
 | 
			
		|||
 | 
			
		||||
    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 @@ class TestReport(BaseReport):
 | 
			
		|||
        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 @@ class CollectReport(BaseReport):
 | 
			
		|||
        return (self.fspath, None, self.fspath)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self) -> str:
 | 
			
		||||
        return "<CollectReport {!r} lenresult={} outcome={!r}>".format(
 | 
			
		||||
            self.nodeid, len(self.result), self.outcome
 | 
			
		||||
        )
 | 
			
		||||
        return f"<CollectReport {self.nodeid!r} lenresult={len(self.result)} outcome={self.outcome!r}>"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CollectErrorRepr(TerminalRepr):
 | 
			
		||||
| 
						 | 
				
			
			@ -444,7 +442,7 @@ class CollectErrorRepr(TerminalRepr):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
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 _report_kwargs_from_json(reportdict: Dict[str, Any]) -> Dict[str, Any]:
 | 
			
		|||
                        description,
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = (
 | 
			
		||||
                ExceptionChainRepr(chain)
 | 
			
		||||
            )
 | 
			
		||||
            exception_info: Union[
 | 
			
		||||
                ExceptionChainRepr, ReprExceptionInfo
 | 
			
		||||
            ] = ExceptionChainRepr(chain)
 | 
			
		||||
        else:
 | 
			
		||||
            exception_info = ReprExceptionInfo(
 | 
			
		||||
                reprtraceback=reprtraceback,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ from _pytest.outcomes import OutcomeException
 | 
			
		|||
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}")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ from functools import total_ordering
 | 
			
		|||
from typing import Literal
 | 
			
		||||
from typing import Optional
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
_ScopeName = Literal["session", "package", "module", "class", "function"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@ from typing import Generator
 | 
			
		|||
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.config.argparsing import Parser
 | 
			
		|||
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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ from typing import Generic
 | 
			
		|||
from typing import TypeVar
 | 
			
		||||
from typing import Union
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["Stash", "StashKey"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,12 +2,13 @@ from typing import List
 | 
			
		|||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 TextIO
 | 
			
		|||
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 BaseReport
 | 
			
		|||
from _pytest.reports import CollectReport
 | 
			
		||||
from _pytest.reports import TestReport
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from _pytest.main import Session
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -671,8 +672,8 @@ class TerminalReporter:
 | 
			
		|||
            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 @@ class TerminalReporter:
 | 
			
		|||
            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:]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,4 +10,5 @@ from time import perf_counter
 | 
			
		|||
from time import sleep
 | 
			
		||||
from time import time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__all__ = ["perf_counter", "sleep", "time"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.nodes import Item
 | 
			
		|||
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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,6 @@ from typing import TYPE_CHECKING
 | 
			
		|||
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 Class
 | 
			
		|||
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 @@ class TestCaseFunction(Function):
 | 
			
		|||
        # 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 @@ class TestCaseFunction(Function):
 | 
			
		|||
                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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import sys
 | 
			
		|||
import _pytest._py.error as error
 | 
			
		||||
import _pytest._py.path as path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sys.modules["py.error"] = error
 | 
			
		||||
sys.modules["py.path"] = path
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -81,6 +81,7 @@ from _pytest.warning_types import PytestUnknownMarkWarning
 | 
			
		|||
from _pytest.warning_types import PytestUnraisableExceptionWarning
 | 
			
		||||
from _pytest.warning_types import PytestWarning
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
set_trace = __pytestPDB.set_trace
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,5 +2,6 @@
 | 
			
		|||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    raise SystemExit(pytest.console_main())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ import multiprocessing
 | 
			
		|||
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 @@ class CommonFSTests:
 | 
			
		|||
    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 @@ class CommonFSTests:
 | 
			
		|||
        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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,10 +6,10 @@ import subprocess
 | 
			
		|||
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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,13 +4,13 @@ import sys
 | 
			
		|||
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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,16 +4,15 @@ from __future__ import annotations
 | 
			
		|||
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 bestrelpath
 | 
			
		|||
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 @@ raise ValueError()
 | 
			
		|||
                    "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 @@ raise ValueError()
 | 
			
		|||
        """
 | 
			
		||||
        raise_suffix = " from None" if mode == "from_none" else ""
 | 
			
		||||
        mod = importasmod(
 | 
			
		||||
            """
 | 
			
		||||
            f"""
 | 
			
		||||
            def f():
 | 
			
		||||
                try:
 | 
			
		||||
                    g()
 | 
			
		||||
| 
						 | 
				
			
			@ -1347,9 +1346,7 @@ raise ValueError()
 | 
			
		|||
                    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 @@ raise ValueError()
 | 
			
		|||
        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 @@ raise ValueError()
 | 
			
		|||
        """
 | 
			
		||||
        exc_handling_code = " from e" if reason == "cause" else ""
 | 
			
		||||
        mod = importasmod(
 | 
			
		||||
            """
 | 
			
		||||
            f"""
 | 
			
		||||
            def f():
 | 
			
		||||
                try:
 | 
			
		||||
                    g()
 | 
			
		||||
| 
						 | 
				
			
			@ -1402,9 +1397,7 @@ raise ValueError()
 | 
			
		|||
                    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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,10 @@ import sys
 | 
			
		|||
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():
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ from unittest import mock
 | 
			
		|||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
config = {"mykey": "ORIGINAL"}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
import argparse
 | 
			
		||||
import pathlib
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
HERE = pathlib.Path(__file__).parent
 | 
			
		||||
TEST_CONTENT = (HERE / "template_test.py").read_bytes()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
from typing import List
 | 
			
		||||
from unittest import IsolatedAsyncioTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
teardowns: List[None] = []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ from typing import List
 | 
			
		|||
 | 
			
		||||
import asynctest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
teardowns: List[None] = []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 @@ def test_exceptions() -> None:
 | 
			
		|||
    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 test_baseexception():
 | 
			
		|||
    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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
import pytest
 | 
			
		||||
from _pytest._io.wcwidth import wcswidth
 | 
			
		||||
from _pytest._io.wcwidth import wcwidth
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,12 +4,12 @@ import os
 | 
			
		|||
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 test_teardown_logging(pytester: Pytester) -> None:
 | 
			
		|||
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(
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 mocked_doctest_runner(monkeypatch):
 | 
			
		|||
    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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,6 @@ from typing import Any
 | 
			
		|||
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.nodes import Collector
 | 
			
		|||
from _pytest.pytester import Pytester
 | 
			
		||||
from _pytest.python import Class
 | 
			
		||||
from _pytest.python import Function
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestModule:
 | 
			
		||||
| 
						 | 
				
			
			@ -54,13 +54,11 @@ class TestModule:
 | 
			
		|||
        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",
 | 
			
		||||
        )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.monkeypatch import MonkeyPatch
 | 
			
		|||
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 @@ class TestFixtureUsages:
 | 
			
		|||
    @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 @@ class TestFixtureUsages:
 | 
			
		|||
 | 
			
		||||
            def test2(no_eq):
 | 
			
		||||
                pass
 | 
			
		||||
        """.format(
 | 
			
		||||
                scope=scope
 | 
			
		||||
            )
 | 
			
		||||
        """
 | 
			
		||||
        )
 | 
			
		||||
        result = pytester.runpytest()
 | 
			
		||||
        result.stdout.fnmatch_lines(["*4 passed*"])
 | 
			
		||||
| 
						 | 
				
			
			@ -2199,7 +2197,7 @@ class TestAutouseManagement:
 | 
			
		|||
                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 @@ class TestFixtureMarker:
 | 
			
		|||
                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 @@ class TestRequestScopeAccess:
 | 
			
		|||
                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 @@ class TestRequestScopeAccess:
 | 
			
		|||
                assert request.config
 | 
			
		||||
            def test_func(arg):
 | 
			
		||||
                pass
 | 
			
		||||
        """
 | 
			
		||||
        """  # noqa: UP031 (python syntax issues)
 | 
			
		||||
            % (scope, ok.split(), error.split())
 | 
			
		||||
        )
 | 
			
		||||
        reprec = pytester.inline_run()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue