mirror of https://github.com/pytest-dev/pytest.git
Migrate from autoflake, black, isort, pyupgrade, flake8 and pydocstyle, to ruff (#11911)
ruff is faster and handle everything we had prior. isort configuration done based on the indication from https://github.com/astral-sh/ruff/issues/4670, previousely based on reorder-python-import (#11896) flake8-docstrings was a wrapper around pydocstyle (now archived) that explicitly asks to use ruff in https://github.com/PyCQA/pydocstyle/pull/658. flake8-typing-import is useful mainly for project that support python 3.7 and the one useful check will be implemented in https://github.com/astral-sh/ruff/issues/2302 We need to keep blacken-doc because ruff does not handle detection of python code inside .md and .rst. The direct link to the repo is now used to avoid a redirection. Manual fixes: - Lines that became too long - % formatting that was not done automatically - type: ignore that were moved around - noqa of hard to fix issues (UP031 generally) - fmt: off and fmt: on that is not really identical between black and ruff - autofix re-order in pre-commit from faster to slower Co-authored-by: Ran Benita <ran@unusedvar.com>
This commit is contained in:
parent
368cc6225e
commit
c11cdfabd1
|
@ -1,14 +1,10 @@
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: 24.1.1
|
rev: "v0.1.15"
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: ruff
|
||||||
args: [--safe, --quiet]
|
args: ["--fix"]
|
||||||
- repo: https://github.com/asottile/blacken-docs
|
- id: ruff-format
|
||||||
rev: 1.16.0
|
|
||||||
hooks:
|
|
||||||
- id: blacken-docs
|
|
||||||
additional_dependencies: [black==24.1.1]
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.5.0
|
rev: v4.5.0
|
||||||
hooks:
|
hooks:
|
||||||
|
@ -20,33 +16,11 @@ repos:
|
||||||
- id: debug-statements
|
- id: debug-statements
|
||||||
exclude: _pytest/(debugging|hookspec).py
|
exclude: _pytest/(debugging|hookspec).py
|
||||||
language_version: python3
|
language_version: python3
|
||||||
- repo: https://github.com/PyCQA/autoflake
|
- repo: https://github.com/adamchainz/blacken-docs
|
||||||
rev: v2.2.1
|
rev: 1.16.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: autoflake
|
- id: blacken-docs
|
||||||
name: autoflake
|
additional_dependencies: [black==24.1.1]
|
||||||
args: ["--in-place", "--remove-unused-variables", "--remove-all-unused-imports"]
|
|
||||||
language: python
|
|
||||||
files: \.py$
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
|
||||||
rev: 6.1.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]
|
|
||||||
- repo: https://github.com/asottile/setup-cfg-fmt
|
- repo: https://github.com/asottile/setup-cfg-fmt
|
||||||
rev: v2.5.0
|
rev: v2.5.0
|
||||||
hooks:
|
hooks:
|
||||||
|
|
|
@ -27,9 +27,6 @@
|
||||||
:target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main
|
:target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main
|
||||||
:alt: pre-commit.ci status
|
: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
|
.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg
|
||||||
:target: https://www.codetriage.com/pytest-dev/pytest
|
:target: https://www.codetriage.com/pytest-dev/pytest
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import cProfile
|
import cProfile
|
||||||
import pstats
|
import pstats
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
# FastFilesCompleter 0.7383 1.0760
|
# FastFilesCompleter 0.7383 1.0760
|
||||||
import timeit
|
import timeit
|
||||||
|
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
"from argcomplete.completers import FilesCompleter as completer",
|
"from argcomplete.completers import FilesCompleter as completer",
|
||||||
"from _pytest._argcomplete import FastFilesCompleter as completer",
|
"from _pytest._argcomplete import FastFilesCompleter as completer",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
SKIP = True
|
SKIP = True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from unittest import TestCase # noqa: F401
|
from unittest import TestCase # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
for i in range(15000):
|
for i in range(15000):
|
||||||
exec(
|
exec(
|
||||||
f"""
|
f"""
|
||||||
|
|
|
@ -23,6 +23,7 @@ from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from _pytest import __version__ as version
|
from _pytest import __version__ as version
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import sphinx.application
|
import sphinx.application
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import os.path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
mydir = os.path.dirname(__file__)
|
mydir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import os.path
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py")
|
failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py")
|
||||||
pytest_plugins = ("pytester",)
|
pytest_plugins = ("pytester",)
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import textwrap
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
pythonlist = ["python3.9", "python3.10", "python3.11"]
|
pythonlist = ["python3.9", "python3.10", "python3.11"]
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,14 +33,12 @@ class Python:
|
||||||
dumpfile = self.picklefile.with_name("dump.py")
|
dumpfile = self.picklefile.with_name("dump.py")
|
||||||
dumpfile.write_text(
|
dumpfile.write_text(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
r"""
|
rf"""
|
||||||
import pickle
|
import pickle
|
||||||
f = open({!r}, 'wb')
|
f = open({str(self.picklefile)!r}, 'wb')
|
||||||
s = pickle.dump({!r}, f, protocol=2)
|
s = pickle.dump({obj!r}, f, protocol=2)
|
||||||
f.close()
|
f.close()
|
||||||
""".format(
|
"""
|
||||||
str(self.picklefile), obj
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
subprocess.run((self.pythonpath, str(dumpfile)), check=True)
|
subprocess.run((self.pythonpath, str(dumpfile)), check=True)
|
||||||
|
@ -48,17 +47,15 @@ class Python:
|
||||||
loadfile = self.picklefile.with_name("load.py")
|
loadfile = self.picklefile.with_name("load.py")
|
||||||
loadfile.write_text(
|
loadfile.write_text(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
r"""
|
rf"""
|
||||||
import pickle
|
import pickle
|
||||||
f = open({!r}, 'rb')
|
f = open({str(self.picklefile)!r}, 'rb')
|
||||||
obj = pickle.load(f)
|
obj = pickle.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
res = eval({!r})
|
res = eval({expression!r})
|
||||||
if not res:
|
if not res:
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
""".format(
|
"""
|
||||||
str(self.picklefile), expression
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
print(loadfile)
|
print(loadfile)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
xfail = pytest.mark.xfail
|
xfail = pytest.mark.xfail
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ from pathlib import Path
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"
|
issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -123,3 +123,58 @@ target-version = ['py38']
|
||||||
[tool.check-wheel-contents]
|
[tool.check-wheel-contents]
|
||||||
# W009: Wheel contains multiple toplevel library entries
|
# W009: Wheel contains multiple toplevel library entries
|
||||||
ignore = "W009"
|
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
|
||||||
|
# Temp for backport 8.0.x
|
||||||
|
"E501",
|
||||||
|
"UP031",
|
||||||
|
]
|
||||||
|
|
||||||
|
[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+.
|
Requires Python3.6+.
|
||||||
"""
|
"""
|
||||||
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
|
||||||
import pypandoc
|
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.
|
`pytest bot <pytestbot@gmail.com>` commit author.
|
||||||
"""
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
import re
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import re
|
||||||
from subprocess import check_call
|
from subprocess import check_call
|
||||||
from subprocess import check_output
|
from subprocess import check_output
|
||||||
from subprocess import run
|
from subprocess import run
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# mypy: disallow-untyped-defs
|
# mypy: disallow-untyped-defs
|
||||||
import sys
|
|
||||||
from subprocess import call
|
from subprocess import call
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
|
|
|
@ -11,13 +11,14 @@ from typing import TypedDict
|
||||||
|
|
||||||
import packaging.version
|
import packaging.version
|
||||||
import platformdirs
|
import platformdirs
|
||||||
import tabulate
|
|
||||||
import wcwidth
|
|
||||||
from requests_cache import CachedResponse
|
from requests_cache import CachedResponse
|
||||||
from requests_cache import CachedSession
|
from requests_cache import CachedSession
|
||||||
from requests_cache import OriginalResponse
|
from requests_cache import OriginalResponse
|
||||||
from requests_cache import SQLiteCache
|
from requests_cache import SQLiteCache
|
||||||
|
import tabulate
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
import wcwidth
|
||||||
|
|
||||||
|
|
||||||
FILE_HEAD = r"""
|
FILE_HEAD = r"""
|
||||||
.. Note this file is autogenerated by scripts/update-plugin-list.py - usually weekly via github action
|
.. 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
|
force refresh in case of last serial mismatch
|
||||||
"""
|
"""
|
||||||
|
|
||||||
response = session.get(f"https://pypi.org/pypi/{name}/json")
|
response = session.get(f"https://pypi.org/pypi/{name}/json")
|
||||||
if int(response.headers.get("X-PyPI-Last-Serial", -1)) != last_serial:
|
if int(response.headers.get("X-PyPI-Last-Serial", -1)) != last_serial:
|
||||||
response = session.get(f"https://pypi.org/pypi/{name}/json", refresh=True)
|
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]:
|
def plugin_definitions(plugins: Iterable[PluginInfo]) -> Iterator[str]:
|
||||||
"""Return RST for the plugin list that fits better on a vertical page."""
|
"""Return RST for the plugin list that fits better on a vertical page."""
|
||||||
|
|
||||||
for plugin in plugins:
|
for plugin in plugins:
|
||||||
yield dedent(
|
yield dedent(
|
||||||
f"""
|
f"""
|
||||||
|
|
|
@ -63,9 +63,9 @@ If things do not work right away:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
from glob import glob
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from glob import glob
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
|
@ -10,6 +10,7 @@ from .code import TracebackEntry
|
||||||
from .source import getrawcode
|
from .source import getrawcode
|
||||||
from .source import Source
|
from .source import Source
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Code",
|
"Code",
|
||||||
"ExceptionInfo",
|
"ExceptionInfo",
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import ast
|
import ast
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
from inspect import CO_VARARGS
|
from inspect import CO_VARARGS
|
||||||
from inspect import CO_VARKEYWORDS
|
from inspect import CO_VARKEYWORDS
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
from traceback import format_exception_only
|
from traceback import format_exception_only
|
||||||
from types import CodeType
|
from types import CodeType
|
||||||
from types import FrameType
|
from types import FrameType
|
||||||
|
@ -50,6 +50,7 @@ from _pytest.deprecated import check_ispytest
|
||||||
from _pytest.pathlib import absolutepath
|
from _pytest.pathlib import absolutepath
|
||||||
from _pytest.pathlib import bestrelpath
|
from _pytest.pathlib import bestrelpath
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[:2] < (3, 11):
|
if sys.version_info[:2] < (3, 11):
|
||||||
from exceptiongroup import BaseExceptionGroup
|
from exceptiongroup import BaseExceptionGroup
|
||||||
|
|
||||||
|
@ -277,9 +278,9 @@ class TracebackEntry:
|
||||||
|
|
||||||
Mostly for internal use.
|
Mostly for internal use.
|
||||||
"""
|
"""
|
||||||
tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = (
|
tbh: Union[
|
||||||
False
|
bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]
|
||||||
)
|
] = False
|
||||||
for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals):
|
for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals):
|
||||||
# in normal cases, f_locals and f_globals are dictionaries
|
# in normal cases, f_locals and f_globals are dictionaries
|
||||||
# however via `exec(...)` / `eval(...)` they can be other types
|
# however via `exec(...)` / `eval(...)` they can be other types
|
||||||
|
@ -376,10 +377,12 @@ class Traceback(List[TracebackEntry]):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ...
|
def __getitem__(self, key: "SupportsIndex") -> TracebackEntry:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, key: slice) -> "Traceback": ...
|
def __getitem__(self, key: slice) -> "Traceback":
|
||||||
|
...
|
||||||
|
|
||||||
def __getitem__(
|
def __getitem__(
|
||||||
self, key: Union["SupportsIndex", slice]
|
self, key: Union["SupportsIndex", slice]
|
||||||
|
@ -484,9 +487,10 @@ class ExceptionInfo(Generic[E]):
|
||||||
|
|
||||||
.. versionadded:: 7.4
|
.. versionadded:: 7.4
|
||||||
"""
|
"""
|
||||||
assert (
|
assert exception.__traceback__, (
|
||||||
exception.__traceback__
|
"Exceptions passed to ExcInfo.from_exception(...)"
|
||||||
), "Exceptions passed to ExcInfo.from_exception(...) must have a non-None __traceback__."
|
" must have a non-None __traceback__."
|
||||||
|
)
|
||||||
exc_info = (type(exception), exception, exception.__traceback__)
|
exc_info = (type(exception), exception, exception.__traceback__)
|
||||||
return cls.from_exc_info(exc_info, exprinfo)
|
return cls.from_exc_info(exc_info, exprinfo)
|
||||||
|
|
||||||
|
@ -585,9 +589,7 @@ class ExceptionInfo(Generic[E]):
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
if self._excinfo is None:
|
if self._excinfo is None:
|
||||||
return "<ExceptionInfo for raises contextmanager>"
|
return "<ExceptionInfo for raises contextmanager>"
|
||||||
return "<{} {} tblen={}>".format(
|
return f"<{self.__class__.__name__} {saferepr(self._excinfo[1])} tblen={len(self.traceback)}>"
|
||||||
self.__class__.__name__, saferepr(self._excinfo[1]), len(self.traceback)
|
|
||||||
)
|
|
||||||
|
|
||||||
def exconly(self, tryshort: bool = False) -> str:
|
def exconly(self, tryshort: bool = False) -> str:
|
||||||
"""Return the exception as a string.
|
"""Return the exception as a string.
|
||||||
|
@ -1015,13 +1017,8 @@ class FormattedExcinfo:
|
||||||
extraline: Optional[str] = (
|
extraline: Optional[str] = (
|
||||||
"!!! Recursion error detected, but an error occurred locating the origin of recursion.\n"
|
"!!! 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"
|
" The following exception happened when comparing locals in the stack frame:\n"
|
||||||
" {exc_type}: {exc_msg}\n"
|
f" {type(e).__name__}: {str(e)}\n"
|
||||||
" Displaying first and last {max_frames} stack frames out of {total}."
|
f" Displaying first and last {max_frames} stack frames out of {len(traceback)}."
|
||||||
).format(
|
|
||||||
exc_type=type(e).__name__,
|
|
||||||
exc_msg=str(e),
|
|
||||||
max_frames=max_frames,
|
|
||||||
total=len(traceback),
|
|
||||||
)
|
)
|
||||||
# Type ignored because adding two instances of a List subtype
|
# Type ignored because adding two instances of a List subtype
|
||||||
# currently incorrectly has type List instead of the subtype.
|
# currently incorrectly has type List instead of the subtype.
|
||||||
|
@ -1053,13 +1050,13 @@ class FormattedExcinfo:
|
||||||
# full support for exception groups added to ExceptionInfo.
|
# full support for exception groups added to ExceptionInfo.
|
||||||
# See https://github.com/pytest-dev/pytest/issues/9159
|
# See https://github.com/pytest-dev/pytest/issues/9159
|
||||||
if isinstance(e, BaseExceptionGroup):
|
if isinstance(e, BaseExceptionGroup):
|
||||||
reprtraceback: Union[ReprTracebackNative, ReprTraceback] = (
|
reprtraceback: Union[
|
||||||
ReprTracebackNative(
|
ReprTracebackNative, ReprTraceback
|
||||||
traceback.format_exception(
|
] = ReprTracebackNative(
|
||||||
type(excinfo_.value),
|
traceback.format_exception(
|
||||||
excinfo_.value,
|
type(excinfo_.value),
|
||||||
excinfo_.traceback[0]._rawentry,
|
excinfo_.value,
|
||||||
)
|
excinfo_.traceback[0]._rawentry,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -1228,7 +1225,6 @@ class ReprEntry(TerminalRepr):
|
||||||
the "E" prefix) using syntax highlighting, taking care to not highlighting the ">"
|
the "E" prefix) using syntax highlighting, taking care to not highlighting the ">"
|
||||||
character, as doing so might break line continuations.
|
character, as doing so might break line continuations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self.lines:
|
if not self.lines:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import ast
|
import ast
|
||||||
|
from bisect import bisect_right
|
||||||
import inspect
|
import inspect
|
||||||
import textwrap
|
import textwrap
|
||||||
import tokenize
|
import tokenize
|
||||||
import types
|
import types
|
||||||
import warnings
|
|
||||||
from bisect import bisect_right
|
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
from typing import List
|
from typing import List
|
||||||
|
@ -12,6 +11,7 @@ from typing import Optional
|
||||||
from typing import overload
|
from typing import overload
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
class Source:
|
class Source:
|
||||||
|
@ -46,10 +46,12 @@ class Source:
|
||||||
__hash__ = None # type: ignore
|
__hash__ = None # type: ignore
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, key: int) -> str: ...
|
def __getitem__(self, key: int) -> str:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __getitem__(self, key: slice) -> "Source": ...
|
def __getitem__(self, key: slice) -> "Source":
|
||||||
|
...
|
||||||
|
|
||||||
def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]:
|
def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]:
|
||||||
if isinstance(key, int):
|
if isinstance(key, int):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from .terminalwriter import get_terminal_width
|
from .terminalwriter import get_terminal_width
|
||||||
from .terminalwriter import TerminalWriter
|
from .terminalwriter import TerminalWriter
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"TerminalWriter",
|
"TerminalWriter",
|
||||||
"get_terminal_width",
|
"get_terminal_width",
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
# useful, thank small children who sleep at night.
|
# useful, thank small children who sleep at night.
|
||||||
import collections as _collections
|
import collections as _collections
|
||||||
import dataclasses as _dataclasses
|
import dataclasses as _dataclasses
|
||||||
|
from io import StringIO as _StringIO
|
||||||
import re
|
import re
|
||||||
import types as _types
|
import types as _types
|
||||||
from io import StringIO as _StringIO
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
|
@ -19,8 +19,8 @@ def _format_repr_exception(exc: BaseException, obj: object) -> str:
|
||||||
raise
|
raise
|
||||||
except BaseException as exc:
|
except BaseException as exc:
|
||||||
exc_info = f"unpresentable exception ({_try_repr_or_str(exc)})"
|
exc_info = f"unpresentable exception ({_try_repr_or_str(exc)})"
|
||||||
return "<[{} raised in repr()] {} object at 0x{:x}>".format(
|
return (
|
||||||
exc_info, type(obj).__name__, id(obj)
|
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
|
This function is a wrapper around the Repr/reprlib functionality of the
|
||||||
stdlib.
|
stdlib.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return SafeRepr(maxsize, use_ascii).repr(obj)
|
return SafeRepr(maxsize, use_ascii).repr(obj)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ from typing import TextIO
|
||||||
|
|
||||||
from .wcwidth import wcswidth
|
from .wcwidth import wcswidth
|
||||||
|
|
||||||
|
|
||||||
# This code was initially copied from py 1.8.1, file _io/terminalwriter.py.
|
# 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):
|
if indents and len(indents) != len(lines):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"indents size ({}) should have same size as lines ({})".format(
|
f"indents size ({len(indents)}) should have same size as lines ({len(lines)})"
|
||||||
len(indents), len(lines)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if not indents:
|
if not indents:
|
||||||
indents = [""] * len(lines)
|
indents = [""] * len(lines)
|
||||||
|
@ -210,8 +209,8 @@ class TerminalWriter:
|
||||||
from pygments.lexers.python import PythonLexer as Lexer
|
from pygments.lexers.python import PythonLexer as Lexer
|
||||||
elif lexer == "diff":
|
elif lexer == "diff":
|
||||||
from pygments.lexers.diff import DiffLexer as Lexer
|
from pygments.lexers.diff import DiffLexer as Lexer
|
||||||
import pygments.util
|
|
||||||
from pygments import highlight
|
from pygments import highlight
|
||||||
|
import pygments.util
|
||||||
except ImportError:
|
except ImportError:
|
||||||
return source
|
return source
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import unicodedata
|
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
import unicodedata
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(100)
|
@lru_cache(100)
|
||||||
|
|
|
@ -9,6 +9,7 @@ from typing import Callable
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing_extensions import ParamSpec
|
from typing_extensions import ParamSpec
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,11 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
|
from contextlib import contextmanager
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import posixpath
|
|
||||||
import sys
|
|
||||||
import uuid
|
|
||||||
import warnings
|
|
||||||
from contextlib import contextmanager
|
|
||||||
from os.path import abspath
|
from os.path import abspath
|
||||||
from os.path import dirname
|
from os.path import dirname
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
|
@ -20,18 +16,23 @@ from os.path import isdir
|
||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
from os.path import islink
|
from os.path import islink
|
||||||
from os.path import normpath
|
from os.path import normpath
|
||||||
|
import posixpath
|
||||||
from stat import S_ISDIR
|
from stat import S_ISDIR
|
||||||
from stat import S_ISLNK
|
from stat import S_ISLNK
|
||||||
from stat import S_ISREG
|
from stat import S_ISREG
|
||||||
|
import sys
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import cast
|
from typing import cast
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
from typing import overload
|
from typing import overload
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
import uuid
|
||||||
|
import warnings
|
||||||
|
|
||||||
from . import error
|
from . import error
|
||||||
|
|
||||||
|
|
||||||
# Moved from local.py.
|
# Moved from local.py.
|
||||||
iswin32 = sys.platform == "win32" or (getattr(os, "_name", False) == "nt")
|
iswin32 = sys.platform == "win32" or (getattr(os, "_name", False) == "nt")
|
||||||
|
|
||||||
|
@ -204,10 +205,12 @@ class Stat:
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self) -> int: ...
|
def size(self) -> int:
|
||||||
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mtime(self) -> float: ...
|
def mtime(self) -> float:
|
||||||
|
...
|
||||||
|
|
||||||
def __getattr__(self, name: str) -> Any:
|
def __getattr__(self, name: str) -> Any:
|
||||||
return getattr(self._osstatresult, "st_" + name)
|
return getattr(self._osstatresult, "st_" + name)
|
||||||
|
@ -674,7 +677,7 @@ class LocalPath:
|
||||||
else:
|
else:
|
||||||
kw.setdefault("dirname", dirname)
|
kw.setdefault("dirname", dirname)
|
||||||
kw.setdefault("sep", self.sep)
|
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
|
return obj
|
||||||
|
|
||||||
def _getbyspec(self, spec: str) -> list[str]:
|
def _getbyspec(self, spec: str) -> list[str]:
|
||||||
|
@ -759,7 +762,10 @@ class LocalPath:
|
||||||
# expected "Callable[[str, Any, Any], TextIOWrapper]" [arg-type]
|
# expected "Callable[[str, Any, Any], TextIOWrapper]" [arg-type]
|
||||||
# Which seems incorrect, given io.open supports the given argument types.
|
# Which seems incorrect, given io.open supports the given argument types.
|
||||||
return error.checked_call(
|
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)
|
return error.checked_call(open, self.strpath, mode)
|
||||||
|
|
||||||
|
@ -778,11 +784,11 @@ class LocalPath:
|
||||||
|
|
||||||
valid checkers::
|
valid checkers::
|
||||||
|
|
||||||
file=1 # is a file
|
file = 1 # is a file
|
||||||
file=0 # is not a file (may not even exist)
|
file = 0 # is not a file (may not even exist)
|
||||||
dir=1 # is a dir
|
dir = 1 # is a dir
|
||||||
link=1 # is a link
|
link = 1 # is a link
|
||||||
exists=1 # exists
|
exists = 1 # exists
|
||||||
|
|
||||||
You can specify multiple checker definitions, for example::
|
You can specify multiple checker definitions, for example::
|
||||||
|
|
||||||
|
@ -960,10 +966,12 @@ class LocalPath:
|
||||||
return p
|
return p
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def stat(self, raising: Literal[True] = ...) -> Stat: ...
|
def stat(self, raising: Literal[True] = ...) -> Stat:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@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:
|
def stat(self, raising: bool = True) -> Stat | None:
|
||||||
"""Return an os.stat() tuple."""
|
"""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]
|
# 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.
|
# Which seems incorrect, given tempfile.mkdtemp supports the given argument types.
|
||||||
path = error.checked_call(
|
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)
|
return cls(path)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from _pytest.config import hookimpl
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest.main import Session
|
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
|
reporting via the pytest_assertrepr_compare hook. This sets up this custom
|
||||||
comparison for the test.
|
comparison for the test.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ihook = item.ihook
|
ihook = item.ihook
|
||||||
|
|
||||||
def callbinrepr(op, left: object, right: object) -> Optional[str]:
|
def callbinrepr(op, left: object, right: object) -> Optional[str]:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Rewrite assertion AST to produce nice error messages."""
|
"""Rewrite assertion AST to produce nice error messages."""
|
||||||
|
|
||||||
import ast
|
import ast
|
||||||
|
from collections import defaultdict
|
||||||
import errno
|
import errno
|
||||||
import functools
|
import functools
|
||||||
import importlib.abc
|
import importlib.abc
|
||||||
|
@ -10,13 +11,12 @@ import io
|
||||||
import itertools
|
import itertools
|
||||||
import marshal
|
import marshal
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from pathlib import PurePath
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import tokenize
|
import tokenize
|
||||||
import types
|
import types
|
||||||
from collections import defaultdict
|
|
||||||
from pathlib import Path
|
|
||||||
from pathlib import PurePath
|
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import IO
|
from typing import IO
|
||||||
|
@ -40,6 +40,7 @@ from _pytest.pathlib import absolutepath
|
||||||
from _pytest.pathlib import fnmatch_ex
|
from _pytest.pathlib import fnmatch_ex
|
||||||
from _pytest.stash import StashKey
|
from _pytest.stash import StashKey
|
||||||
|
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
from _pytest.assertion.util import format_explanation as _format_explanation # noqa:F401, isort:skip
|
from _pytest.assertion.util import format_explanation as _format_explanation # noqa:F401, isort:skip
|
||||||
# fmt:on
|
# fmt:on
|
||||||
|
@ -671,9 +672,9 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||||
self.enable_assertion_pass_hook = False
|
self.enable_assertion_pass_hook = False
|
||||||
self.source = source
|
self.source = source
|
||||||
self.scope: tuple[ast.AST, ...] = ()
|
self.scope: tuple[ast.AST, ...] = ()
|
||||||
self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = (
|
self.variables_overwrite: defaultdict[
|
||||||
defaultdict(dict)
|
tuple[ast.AST, ...], Dict[str, str]
|
||||||
)
|
] = defaultdict(dict)
|
||||||
|
|
||||||
def run(self, mod: ast.Module) -> None:
|
def run(self, mod: ast.Module) -> None:
|
||||||
"""Find all assert statements in *mod* and rewrite them."""
|
"""Find all assert statements in *mod* and rewrite them."""
|
||||||
|
@ -1019,9 +1020,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
pytest_temp = self.variable()
|
pytest_temp = self.variable()
|
||||||
self.variables_overwrite[self.scope][
|
self.variables_overwrite[self.scope][v.left.target.id] = v.left # type:ignore[assignment]
|
||||||
v.left.target.id
|
|
||||||
] = v.left # type:ignore[assignment]
|
|
||||||
v.left.target.id = pytest_temp
|
v.left.target.id = pytest_temp
|
||||||
self.push_format_context()
|
self.push_format_context()
|
||||||
res, expl = self.visit(v)
|
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(
|
if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite.get(
|
||||||
self.scope, {}
|
self.scope, {}
|
||||||
):
|
):
|
||||||
arg = self.variables_overwrite[self.scope][
|
arg = self.variables_overwrite[self.scope][arg.id] # type:ignore[assignment]
|
||||||
arg.id
|
|
||||||
] # type:ignore[assignment]
|
|
||||||
res, expl = self.visit(arg)
|
res, expl = self.visit(arg)
|
||||||
arg_expls.append(expl)
|
arg_expls.append(expl)
|
||||||
new_args.append(res)
|
new_args.append(res)
|
||||||
|
@ -1075,9 +1072,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||||
if isinstance(
|
if isinstance(
|
||||||
keyword.value, ast.Name
|
keyword.value, ast.Name
|
||||||
) and keyword.value.id in self.variables_overwrite.get(self.scope, {}):
|
) and keyword.value.id in self.variables_overwrite.get(self.scope, {}):
|
||||||
keyword.value = self.variables_overwrite[self.scope][
|
keyword.value = self.variables_overwrite[self.scope][keyword.value.id] # type:ignore[assignment]
|
||||||
keyword.value.id
|
|
||||||
] # type:ignore[assignment]
|
|
||||||
res, expl = self.visit(keyword.value)
|
res, expl = self.visit(keyword.value)
|
||||||
new_kwargs.append(ast.keyword(keyword.arg, res))
|
new_kwargs.append(ast.keyword(keyword.arg, res))
|
||||||
if keyword.arg:
|
if keyword.arg:
|
||||||
|
@ -1114,13 +1109,9 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||||
if isinstance(
|
if isinstance(
|
||||||
comp.left, ast.Name
|
comp.left, ast.Name
|
||||||
) and comp.left.id in self.variables_overwrite.get(self.scope, {}):
|
) and comp.left.id in self.variables_overwrite.get(self.scope, {}):
|
||||||
comp.left = self.variables_overwrite[self.scope][
|
comp.left = self.variables_overwrite[self.scope][comp.left.id] # type:ignore[assignment]
|
||||||
comp.left.id
|
|
||||||
] # type:ignore[assignment]
|
|
||||||
if isinstance(comp.left, ast.NamedExpr):
|
if isinstance(comp.left, ast.NamedExpr):
|
||||||
self.variables_overwrite[self.scope][
|
self.variables_overwrite[self.scope][comp.left.target.id] = comp.left # type:ignore[assignment]
|
||||||
comp.left.target.id
|
|
||||||
] = comp.left # type:ignore[assignment]
|
|
||||||
left_res, left_expl = self.visit(comp.left)
|
left_res, left_expl = self.visit(comp.left)
|
||||||
if isinstance(comp.left, (ast.Compare, ast.BoolOp)):
|
if isinstance(comp.left, (ast.Compare, ast.BoolOp)):
|
||||||
left_expl = f"({left_expl})"
|
left_expl = f"({left_expl})"
|
||||||
|
@ -1138,9 +1129,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||||
and next_operand.target.id == left_res.id
|
and next_operand.target.id == left_res.id
|
||||||
):
|
):
|
||||||
next_operand.target.id = self.variable()
|
next_operand.target.id = self.variable()
|
||||||
self.variables_overwrite[self.scope][
|
self.variables_overwrite[self.scope][left_res.id] = next_operand # type:ignore[assignment]
|
||||||
left_res.id
|
|
||||||
] = next_operand # type:ignore[assignment]
|
|
||||||
next_res, next_expl = self.visit(next_operand)
|
next_res, next_expl = self.visit(next_operand)
|
||||||
if isinstance(next_operand, (ast.Compare, ast.BoolOp)):
|
if isinstance(next_operand, (ast.Compare, ast.BoolOp)):
|
||||||
next_expl = f"({next_expl})"
|
next_expl = f"({next_expl})"
|
||||||
|
|
|
@ -11,6 +11,7 @@ from _pytest.assertion import util
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_MAX_LINES = 8
|
DEFAULT_MAX_LINES = 8
|
||||||
DEFAULT_MAX_CHARS = 8 * 80
|
DEFAULT_MAX_CHARS = 8 * 80
|
||||||
USAGE_MSG = "use '-vv' to show"
|
USAGE_MSG = "use '-vv' to show"
|
||||||
|
|
|
@ -15,13 +15,14 @@ from typing import Protocol
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
from unicodedata import normalize
|
from unicodedata import normalize
|
||||||
|
|
||||||
import _pytest._code
|
|
||||||
from _pytest import outcomes
|
from _pytest import outcomes
|
||||||
|
import _pytest._code
|
||||||
from _pytest._io.pprint import PrettyPrinter
|
from _pytest._io.pprint import PrettyPrinter
|
||||||
from _pytest._io.saferepr import saferepr
|
from _pytest._io.saferepr import saferepr
|
||||||
from _pytest._io.saferepr import saferepr_unlimited
|
from _pytest._io.saferepr import saferepr_unlimited
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
|
|
||||||
|
|
||||||
# The _reprcompare attribute on the util module is used by the new assertion
|
# The _reprcompare attribute on the util module is used by the new assertion
|
||||||
# interpretation code and assertion rewriter to detect this plugin was
|
# interpretation code and assertion rewriter to detect this plugin was
|
||||||
# loaded and in turn call the hooks defined here as part of the
|
# 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:
|
if i > 42:
|
||||||
i -= 10 # Provide some context
|
i -= 10 # Provide some context
|
||||||
explanation += [
|
explanation += [
|
||||||
"Skipping {} identical trailing "
|
f"Skipping {i} identical trailing "
|
||||||
"characters in diff, use -v to show".format(i)
|
"characters in diff, use -v to show"
|
||||||
]
|
]
|
||||||
left = left[:-i]
|
left = left[:-i]
|
||||||
right = right[:-i]
|
right = right[:-i]
|
||||||
|
|
|
@ -32,6 +32,7 @@ from _pytest.nodes import Directory
|
||||||
from _pytest.nodes import File
|
from _pytest.nodes import File
|
||||||
from _pytest.reports import TestReport
|
from _pytest.reports import TestReport
|
||||||
|
|
||||||
|
|
||||||
README_CONTENT = """\
|
README_CONTENT = """\
|
||||||
# pytest cache directory #
|
# pytest cache directory #
|
||||||
|
|
||||||
|
@ -368,15 +369,13 @@ class LFPlugin:
|
||||||
|
|
||||||
noun = "failure" if self._previously_failed_count == 1 else "failures"
|
noun = "failure" if self._previously_failed_count == 1 else "failures"
|
||||||
suffix = " first" if self.config.getoption("failedfirst") else ""
|
suffix = " first" if self.config.getoption("failedfirst") else ""
|
||||||
self._report_status = "rerun previous {count} {noun}{suffix}".format(
|
self._report_status = (
|
||||||
count=self._previously_failed_count, suffix=suffix, noun=noun
|
f"rerun previous {self._previously_failed_count} {noun}{suffix}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._skipped_files > 0:
|
if self._skipped_files > 0:
|
||||||
files_noun = "file" if self._skipped_files == 1 else "files"
|
files_noun = "file" if self._skipped_files == 1 else "files"
|
||||||
self._report_status += " (skipped {files} {files_noun})".format(
|
self._report_status += f" (skipped {self._skipped_files} {files_noun})"
|
||||||
files=self._skipped_files, files_noun=files_noun
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self._report_status = "no previously failed tests, "
|
self._report_status = "no previously failed tests, "
|
||||||
if self.config.getoption("last_failed_no_failures") == "none":
|
if self.config.getoption("last_failed_no_failures") == "none":
|
||||||
|
|
|
@ -4,9 +4,9 @@ import abc
|
||||||
import collections
|
import collections
|
||||||
import contextlib
|
import contextlib
|
||||||
import io
|
import io
|
||||||
|
from io import UnsupportedOperation
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from io import UnsupportedOperation
|
|
||||||
from tempfile import TemporaryFile
|
from tempfile import TemporaryFile
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -39,6 +39,7 @@ from _pytest.nodes import File
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
from _pytest.reports import CollectReport
|
from _pytest.reports import CollectReport
|
||||||
|
|
||||||
|
|
||||||
_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
|
_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
|
||||||
|
|
||||||
|
|
||||||
|
@ -790,9 +791,7 @@ class CaptureManager:
|
||||||
current_fixture = self._capture_fixture.request.fixturename
|
current_fixture = self._capture_fixture.request.fixturename
|
||||||
requested_fixture = capture_fixture.request.fixturename
|
requested_fixture = capture_fixture.request.fixturename
|
||||||
capture_fixture.request.raiseerror(
|
capture_fixture.request.raiseerror(
|
||||||
"cannot use {} and {} at the same time".format(
|
f"cannot use {requested_fixture} and {current_fixture} at the same time"
|
||||||
requested_fixture, current_fixture
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
self._capture_fixture = capture_fixture
|
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>`.
|
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def test_output(capsys):
|
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>`.
|
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def test_output(capsysbinary):
|
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>`.
|
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def test_system_echo(capfd):
|
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>`.
|
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def test_system_echo(capfdbinary):
|
def test_system_echo(capfdbinary):
|
||||||
|
|
|
@ -6,11 +6,11 @@ import dataclasses
|
||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from inspect import Parameter
|
from inspect import Parameter
|
||||||
from inspect import signature
|
from inspect import signature
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
@ -19,6 +19,7 @@ from typing import TypeVar
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
|
||||||
_T = TypeVar("_T")
|
_T = TypeVar("_T")
|
||||||
_S = TypeVar("_S")
|
_S = TypeVar("_S")
|
||||||
|
|
||||||
|
@ -258,9 +259,7 @@ def get_real_func(obj):
|
||||||
from _pytest._io.saferepr import saferepr
|
from _pytest._io.saferepr import saferepr
|
||||||
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
("could not find real function of {start}\nstopped at {current}").format(
|
f"could not find real function of {saferepr(start_obj)}\nstopped at {saferepr(obj)}"
|
||||||
start=saferepr(start_obj), current=saferepr(obj)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if isinstance(obj, functools.partial):
|
if isinstance(obj, functools.partial):
|
||||||
obj = obj.func
|
obj = obj.func
|
||||||
|
|
|
@ -5,18 +5,17 @@ import collections.abc
|
||||||
import copy
|
import copy
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import enum
|
import enum
|
||||||
|
from functools import lru_cache
|
||||||
import glob
|
import glob
|
||||||
import importlib.metadata
|
import importlib.metadata
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
import types
|
|
||||||
import warnings
|
|
||||||
from functools import lru_cache
|
|
||||||
from pathlib import Path
|
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
import types
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -38,6 +37,7 @@ from typing import Tuple
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pluggy
|
import pluggy
|
||||||
from pluggy import HookimplMarker
|
from pluggy import HookimplMarker
|
||||||
|
@ -46,16 +46,16 @@ from pluggy import HookspecMarker
|
||||||
from pluggy import HookspecOpts
|
from pluggy import HookspecOpts
|
||||||
from pluggy import PluginManager
|
from pluggy import PluginManager
|
||||||
|
|
||||||
import _pytest._code
|
|
||||||
import _pytest.deprecated
|
|
||||||
import _pytest.hookspec
|
|
||||||
from .compat import PathAwareHookProxy
|
from .compat import PathAwareHookProxy
|
||||||
from .exceptions import PrintHelp as PrintHelp
|
from .exceptions import PrintHelp as PrintHelp
|
||||||
from .exceptions import UsageError as UsageError
|
from .exceptions import UsageError as UsageError
|
||||||
from .findpaths import determine_setup
|
from .findpaths import determine_setup
|
||||||
|
import _pytest._code
|
||||||
from _pytest._code import ExceptionInfo
|
from _pytest._code import ExceptionInfo
|
||||||
from _pytest._code import filter_traceback
|
from _pytest._code import filter_traceback
|
||||||
from _pytest._io import TerminalWriter
|
from _pytest._io import TerminalWriter
|
||||||
|
import _pytest.deprecated
|
||||||
|
import _pytest.hookspec
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
from _pytest.outcomes import Skipped
|
from _pytest.outcomes import Skipped
|
||||||
from _pytest.pathlib import absolutepath
|
from _pytest.pathlib import absolutepath
|
||||||
|
@ -68,6 +68,7 @@ from _pytest.stash import Stash
|
||||||
from _pytest.warning_types import PytestConfigWarning
|
from _pytest.warning_types import PytestConfigWarning
|
||||||
from _pytest.warning_types import warn_explicit_for
|
from _pytest.warning_types import warn_explicit_for
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .argparsing import Argument
|
from .argparsing import Argument
|
||||||
from .argparsing import Parser
|
from .argparsing import Parser
|
||||||
|
@ -123,9 +124,7 @@ class ConftestImportFailure(Exception):
|
||||||
self.excinfo = excinfo
|
self.excinfo = excinfo
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return "{}: {} (from {})".format(
|
return f"{self.excinfo[0].__name__}: {self.excinfo[1]} (from {self.path})"
|
||||||
self.excinfo[0].__name__, self.excinfo[1], self.path
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def filter_traceback_for_conftest_import_failure(
|
def filter_traceback_for_conftest_import_failure(
|
||||||
|
@ -814,7 +813,7 @@ class PytestPluginManager(PluginManager):
|
||||||
|
|
||||||
|
|
||||||
def _get_plugin_specs_as_list(
|
def _get_plugin_specs_as_list(
|
||||||
specs: Union[None, types.ModuleType, str, Sequence[str]]
|
specs: Union[None, types.ModuleType, str, Sequence[str]],
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
"""Parse a plugins specification into a list of plugin names."""
|
"""Parse a plugins specification into a list of plugin names."""
|
||||||
# None means empty.
|
# None means empty.
|
||||||
|
@ -1626,9 +1625,7 @@ class Config:
|
||||||
key, user_ini_value = ini_config.split("=", 1)
|
key, user_ini_value = ini_config.split("=", 1)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
"-o/--override-ini expects option=value style (got: {!r}).".format(
|
f"-o/--override-ini expects option=value style (got: {ini_config!r})."
|
||||||
ini_config
|
|
||||||
)
|
|
||||||
) from e
|
) from e
|
||||||
else:
|
else:
|
||||||
if key == name:
|
if key == name:
|
||||||
|
@ -1686,7 +1683,6 @@ class Config:
|
||||||
can be used to explicitly use the global verbosity level.
|
can be used to explicitly use the global verbosity level.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
# content of pytest.ini
|
# content of pytest.ini
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
|
from gettext import gettext
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
|
||||||
from gettext import gettext
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
@ -16,6 +15,7 @@ from typing import Optional
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
import _pytest._io
|
import _pytest._io
|
||||||
from _pytest.config.exceptions import UsageError
|
from _pytest.config.exceptions import UsageError
|
||||||
|
@ -24,6 +24,7 @@ from _pytest.deprecated import ARGUMENT_TYPE_STR
|
||||||
from _pytest.deprecated import ARGUMENT_TYPE_STR_CHOICE
|
from _pytest.deprecated import ARGUMENT_TYPE_STR_CHOICE
|
||||||
from _pytest.deprecated import check_ispytest
|
from _pytest.deprecated import check_ispytest
|
||||||
|
|
||||||
|
|
||||||
FILE_OR_DIR = "file_or_dir"
|
FILE_OR_DIR = "file_or_dir"
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +220,7 @@ class Parser:
|
||||||
|
|
||||||
|
|
||||||
def get_ini_default_for_type(
|
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:
|
) -> Any:
|
||||||
"""
|
"""
|
||||||
Used by addini to get the default value for a given ini-option type, when
|
Used by addini to get the default value for a given ini-option type, when
|
||||||
|
@ -480,7 +481,7 @@ class MyOptionParser(argparse.ArgumentParser):
|
||||||
) -> Optional[Tuple[Optional[argparse.Action], str, Optional[str]]]:
|
) -> Optional[Tuple[Optional[argparse.Action], str, Optional[str]]]:
|
||||||
if not arg_string:
|
if not arg_string:
|
||||||
return None
|
return None
|
||||||
if not arg_string[0] in self.prefix_chars:
|
if arg_string[0] not in self.prefix_chars:
|
||||||
return None
|
return None
|
||||||
if arg_string in self._option_string_actions:
|
if arg_string in self._option_string_actions:
|
||||||
action = self._option_string_actions[arg_string]
|
action = self._option_string_actions[arg_string]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import warnings
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Mapping
|
from typing import Mapping
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pluggy
|
import pluggy
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ from ..compat import LEGACY_PATH
|
||||||
from ..compat import legacy_path
|
from ..compat import legacy_path
|
||||||
from ..deprecated import HOOK_LEGACY_PATH_ARG
|
from ..deprecated import HOOK_LEGACY_PATH_ARG
|
||||||
|
|
||||||
|
|
||||||
# hookname: (Path, LEGACY_PATH)
|
# hookname: (Path, LEGACY_PATH)
|
||||||
imply_paths_hooks: Mapping[str, tuple[str, str]] = {
|
imply_paths_hooks: Mapping[str, tuple[str, str]] = {
|
||||||
"pytest_ignore_collect": ("collection_path", "path"),
|
"pytest_ignore_collect": ("collection_path", "path"),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
from typing import List
|
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.
|
Return None if the file does not contain valid pytest configuration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Configuration from ini files are obtained from the [pytest] section, if present.
|
# Configuration from ini files are obtained from the [pytest] section, if present.
|
||||||
if filepath.suffix == ".ini":
|
if filepath.suffix == ".ini":
|
||||||
iniconfig = _parse_ini_config(filepath)
|
iniconfig = _parse_ini_config(filepath)
|
||||||
|
@ -211,9 +210,7 @@ def determine_setup(
|
||||||
rootdir = absolutepath(os.path.expandvars(rootdir_cmd_arg))
|
rootdir = absolutepath(os.path.expandvars(rootdir_cmd_arg))
|
||||||
if not rootdir.is_dir():
|
if not rootdir.is_dir():
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
"Directory '{}' not found. Check your '--rootdir' option.".format(
|
f"Directory '{rootdir}' not found. Check your '--rootdir' option."
|
||||||
rootdir
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
assert rootdir is not None
|
assert rootdir is not None
|
||||||
return rootdir, inipath, inicfg or {}
|
return rootdir, inipath, inicfg or {}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import argparse
|
||||||
import functools
|
import functools
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
import unittest
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
@ -14,6 +13,7 @@ from typing import Tuple
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import unittest
|
||||||
|
|
||||||
from _pytest import outcomes
|
from _pytest import outcomes
|
||||||
from _pytest._code import ExceptionInfo
|
from _pytest._code import ExceptionInfo
|
||||||
|
@ -26,6 +26,7 @@ from _pytest.config.exceptions import UsageError
|
||||||
from _pytest.nodes import Node
|
from _pytest.nodes import Node
|
||||||
from _pytest.reports import BaseReport
|
from _pytest.reports import BaseReport
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest.capture import CaptureManager
|
from _pytest.capture import CaptureManager
|
||||||
from _pytest.runner import CallInfo
|
from _pytest.runner import CallInfo
|
||||||
|
@ -264,8 +265,7 @@ class pytestPDB:
|
||||||
elif capturing:
|
elif capturing:
|
||||||
tw.sep(
|
tw.sep(
|
||||||
">",
|
">",
|
||||||
"PDB %s (IO-capturing turned off for %s)"
|
f"PDB {method} (IO-capturing turned off for {capturing})",
|
||||||
% (method, capturing),
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
tw.sep(">", f"PDB {method}")
|
tw.sep(">", f"PDB {method}")
|
||||||
|
|
|
@ -16,6 +16,7 @@ from _pytest.warning_types import PytestRemovedIn8Warning
|
||||||
from _pytest.warning_types import PytestRemovedIn9Warning
|
from _pytest.warning_types import PytestRemovedIn9Warning
|
||||||
from _pytest.warning_types import UnformattedWarning
|
from _pytest.warning_types import UnformattedWarning
|
||||||
|
|
||||||
|
|
||||||
# set of plugins which have been integrated into the core; we use this list to ignore
|
# set of plugins which have been integrated into the core; we use this list to ignore
|
||||||
# them during registration to avoid conflicts
|
# them during registration to avoid conflicts
|
||||||
DEPRECATED_EXTERNAL_PLUGINS = {
|
DEPRECATED_EXTERNAL_PLUGINS = {
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
"""Discover and run doctests in modules and test files."""
|
"""Discover and run doctests in modules and test files."""
|
||||||
|
|
||||||
import bdb
|
import bdb
|
||||||
|
from contextlib import contextmanager
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import types
|
import types
|
||||||
import warnings
|
|
||||||
from contextlib import contextmanager
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -24,6 +23,7 @@ from typing import Tuple
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
from _pytest import outcomes
|
from _pytest import outcomes
|
||||||
from _pytest._code.code import ExceptionInfo
|
from _pytest._code.code import ExceptionInfo
|
||||||
|
@ -45,6 +45,7 @@ from _pytest.python import Module
|
||||||
from _pytest.python_api import approx
|
from _pytest.python_api import approx
|
||||||
from _pytest.warning_types import PytestWarning
|
from _pytest.warning_types import PytestWarning
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import doctest
|
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))
|
return real_unwrap(func, stop=lambda obj: _is_mocked(obj) or _stop(func))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
warnings.warn(
|
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. "
|
"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,
|
PytestWarning,
|
||||||
)
|
)
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -2,11 +2,12 @@ import os
|
||||||
import sys
|
import sys
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
from _pytest.stash import StashKey
|
from _pytest.stash import StashKey
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
fault_handler_original_stderr_fd_key = StashKey[int]()
|
fault_handler_original_stderr_fd_key = StashKey[int]()
|
||||||
fault_handler_stderr_fd_key = StashKey[int]()
|
fault_handler_stderr_fd_key = StashKey[int]()
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import abc
|
import abc
|
||||||
|
from collections import defaultdict
|
||||||
|
from collections import deque
|
||||||
|
from contextlib import suppress
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
import warnings
|
|
||||||
from collections import defaultdict
|
|
||||||
from collections import deque
|
|
||||||
from contextlib import suppress
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import AbstractSet
|
from typing import AbstractSet
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -30,6 +29,7 @@ from typing import Tuple
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
|
@ -66,6 +66,7 @@ from _pytest.scope import _ScopeName
|
||||||
from _pytest.scope import HIGH_SCOPES
|
from _pytest.scope import HIGH_SCOPES
|
||||||
from _pytest.scope import Scope
|
from _pytest.scope import Scope
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Deque
|
from typing import Deque
|
||||||
|
|
||||||
|
@ -606,13 +607,9 @@ class FixtureRequest(abc.ABC):
|
||||||
fixtures_not_supported = getattr(funcitem, "nofuncargs", False)
|
fixtures_not_supported = getattr(funcitem, "nofuncargs", False)
|
||||||
if has_params and fixtures_not_supported:
|
if has_params and fixtures_not_supported:
|
||||||
msg = (
|
msg = (
|
||||||
"{name} does not support fixtures, maybe unittest.TestCase subclass?\n"
|
f"{funcitem.name} does not support fixtures, maybe unittest.TestCase subclass?\n"
|
||||||
"Node id: {nodeid}\n"
|
f"Node id: {funcitem.nodeid}\n"
|
||||||
"Function type: {typename}"
|
f"Function type: {type(funcitem).__name__}"
|
||||||
).format(
|
|
||||||
name=funcitem.name,
|
|
||||||
nodeid=funcitem.nodeid,
|
|
||||||
typename=type(funcitem).__name__,
|
|
||||||
)
|
)
|
||||||
fail(msg, pytrace=False)
|
fail(msg, pytrace=False)
|
||||||
if has_params:
|
if has_params:
|
||||||
|
@ -745,9 +742,7 @@ class SubRequest(FixtureRequest):
|
||||||
if node is None and scope is Scope.Class:
|
if node is None and scope is Scope.Class:
|
||||||
# Fallback to function item itself.
|
# Fallback to function item itself.
|
||||||
node = self._pyfuncitem
|
node = self._pyfuncitem
|
||||||
assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format(
|
assert node, f'Could not obtain a node for scope "{scope}" for function {self._pyfuncitem!r}'
|
||||||
scope, self._pyfuncitem
|
|
||||||
)
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def _check_scope(
|
def _check_scope(
|
||||||
|
@ -851,8 +846,8 @@ class FixtureLookupError(LookupError):
|
||||||
if faclist:
|
if faclist:
|
||||||
available.add(name)
|
available.add(name)
|
||||||
if self.argname in available:
|
if self.argname in available:
|
||||||
msg = " recursive dependency involving fixture '{}' detected".format(
|
msg = (
|
||||||
self.argname
|
f" recursive dependency involving fixture '{self.argname}' detected"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg = f"fixture '{self.argname}' not found"
|
msg = f"fixture '{self.argname}' not found"
|
||||||
|
@ -946,15 +941,13 @@ def _eval_scope_callable(
|
||||||
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg]
|
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"Error evaluating {} while defining fixture '{}'.\n"
|
f"Error evaluating {scope_callable} while defining fixture '{fixture_name}'.\n"
|
||||||
"Expected a function with the signature (*, fixture_name, config)".format(
|
"Expected a function with the signature (*, fixture_name, config)"
|
||||||
scope_callable, fixture_name
|
|
||||||
)
|
|
||||||
) from e
|
) from e
|
||||||
if not isinstance(result, str):
|
if not isinstance(result, str):
|
||||||
fail(
|
fail(
|
||||||
"Expected {} to return a 'str' while defining fixture '{}', but it returned:\n"
|
f"Expected {scope_callable} to return a 'str' while defining fixture '{fixture_name}', but it returned:\n"
|
||||||
"{!r}".format(scope_callable, fixture_name, result),
|
f"{result!r}",
|
||||||
pytrace=False,
|
pytrace=False,
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
@ -1098,9 +1091,7 @@ class FixtureDef(Generic[FixtureValue]):
|
||||||
return request.param_index if not hasattr(request, "param") else request.param
|
return request.param_index if not hasattr(request, "param") else request.param
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "<FixtureDef argname={!r} scope={!r} baseid={!r}>".format(
|
return f"<FixtureDef argname={self.argname!r} scope={self.scope!r} baseid={self.baseid!r}>"
|
||||||
self.argname, self.scope, self.baseid
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_fixture_function(
|
def resolve_fixture_function(
|
||||||
|
@ -1121,7 +1112,8 @@ def resolve_fixture_function(
|
||||||
# Handle the case where fixture is defined not in a test class, but some other class
|
# 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.
|
# (for example a plugin class with a fixture), see #2270.
|
||||||
if hasattr(fixturefunc, "__self__") and not isinstance(
|
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
|
return fixturefunc
|
||||||
fixturefunc = getimfunc(fixturedef.func)
|
fixturefunc = getimfunc(fixturedef.func)
|
||||||
|
@ -1216,9 +1208,7 @@ class FixtureFunctionMarker:
|
||||||
if name == "request":
|
if name == "request":
|
||||||
location = getlocation(function)
|
location = getlocation(function)
|
||||||
fail(
|
fail(
|
||||||
"'request' is a reserved word for fixtures, use another name:\n {}".format(
|
f"'request' is a reserved word for fixtures, use another name:\n {location}",
|
||||||
location
|
|
||||||
),
|
|
||||||
pytrace=False,
|
pytrace=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1238,7 +1228,8 @@ def fixture(
|
||||||
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
|
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
|
||||||
] = ...,
|
] = ...,
|
||||||
name: Optional[str] = ...,
|
name: Optional[str] = ...,
|
||||||
) -> FixtureFunction: ...
|
) -> FixtureFunction:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
|
@ -1252,7 +1243,8 @@ def fixture( # noqa: F811
|
||||||
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
|
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
|
||||||
] = ...,
|
] = ...,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
) -> FixtureFunctionMarker: ...
|
) -> FixtureFunctionMarker:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
def fixture( # noqa: F811
|
def fixture( # noqa: F811
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
"""Version info, help messages, tracing configuration."""
|
"""Version info, help messages, tracing configuration."""
|
||||||
|
|
||||||
|
from argparse import Action
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from argparse import Action
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import PrintHelp
|
from _pytest.config import PrintHelp
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.terminal import TerminalReporter
|
from _pytest.terminal import TerminalReporter
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
class HelpAction(Action):
|
class HelpAction(Action):
|
||||||
|
@ -136,9 +136,7 @@ def pytest_cmdline_parse() -> Generator[None, Config, Config]:
|
||||||
def showversion(config: Config) -> None:
|
def showversion(config: Config) -> None:
|
||||||
if config.option.version > 1:
|
if config.option.version > 1:
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
"This is pytest version {}, imported from {}\n".format(
|
f"This is pytest version {pytest.__version__}, imported from {pytest.__file__}\n"
|
||||||
pytest.__version__, pytest.__file__
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
plugininfo = getpluginversioninfo(config)
|
plugininfo = getpluginversioninfo(config)
|
||||||
if plugininfo:
|
if plugininfo:
|
||||||
|
|
|
@ -16,10 +16,11 @@ from pluggy import HookspecMarker
|
||||||
|
|
||||||
from _pytest.deprecated import WARNING_CMDLINE_PREPARSE_HOOK
|
from _pytest.deprecated import WARNING_CMDLINE_PREPARSE_HOOK
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import pdb
|
import pdb
|
||||||
import warnings
|
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
import warnings
|
||||||
|
|
||||||
from _pytest._code.code import ExceptionInfo
|
from _pytest._code.code import ExceptionInfo
|
||||||
from _pytest._code.code import ExceptionRepr
|
from _pytest._code.code import ExceptionRepr
|
||||||
|
|
|
@ -7,12 +7,11 @@ Output conforms to
|
||||||
https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
|
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 functools
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
|
@ -20,8 +19,8 @@ from typing import Match
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
from _pytest import timing
|
from _pytest import timing
|
||||||
from _pytest._code.code import ExceptionRepr
|
from _pytest._code.code import ExceptionRepr
|
||||||
|
@ -33,6 +32,8 @@ from _pytest.fixtures import FixtureRequest
|
||||||
from _pytest.reports import TestReport
|
from _pytest.reports import TestReport
|
||||||
from _pytest.stash import StashKey
|
from _pytest.stash import StashKey
|
||||||
from _pytest.terminal import TerminalReporter
|
from _pytest.terminal import TerminalReporter
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
xml_key = StashKey["LogXML"]()
|
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"):
|
if xml is not None and xml.family not in ("xunit1", "legacy"):
|
||||||
request.node.warn(
|
request.node.warn(
|
||||||
PytestWarning(
|
PytestWarning(
|
||||||
"{fixture_name} is incompatible with junit_family '{family}' (use 'legacy' or 'xunit1')".format(
|
f"{fixture_name} is incompatible with junit_family '{xml.family}' (use 'legacy' or 'xunit1')"
|
||||||
fixture_name=fixture_name, family=xml.family
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -367,7 +366,6 @@ def record_testsuite_property(request: FixtureRequest) -> Callable[[str, object]
|
||||||
`pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
|
`pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
|
||||||
:issue:`7767` for details.
|
:issue:`7767` for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
|
||||||
def record_func(name: str, value: object) -> None:
|
def record_func(name: str, value: object) -> None:
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"""Add backward compatibility support for the legacy py path type."""
|
"""Add backward compatibility support for the legacy py path type."""
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
|
from pathlib import Path
|
||||||
import shlex
|
import shlex
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
|
||||||
from typing import Final
|
from typing import Final
|
||||||
from typing import final
|
from typing import final
|
||||||
from typing import List
|
from typing import List
|
||||||
|
@ -33,6 +33,7 @@ from _pytest.pytester import RunResult
|
||||||
from _pytest.terminal import TerminalReporter
|
from _pytest.terminal import TerminalReporter
|
||||||
from _pytest.tmpdir import TempPathFactory
|
from _pytest.tmpdir import TempPathFactory
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import pexpect
|
import pexpect
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
"""Access and control log capturing."""
|
"""Access and control log capturing."""
|
||||||
|
|
||||||
import io
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from contextlib import nullcontext
|
from contextlib import nullcontext
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from datetime import timezone
|
from datetime import timezone
|
||||||
|
import io
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
import logging
|
||||||
from logging import LogRecord
|
from logging import LogRecord
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import re
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import AbstractSet
|
from typing import AbstractSet
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -44,6 +44,7 @@ from _pytest.main import Session
|
||||||
from _pytest.stash import StashKey
|
from _pytest.stash import StashKey
|
||||||
from _pytest.terminal import TerminalReporter
|
from _pytest.terminal import TerminalReporter
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
logging_StreamHandler = logging.StreamHandler[StringIO]
|
logging_StreamHandler = logging.StreamHandler[StringIO]
|
||||||
else:
|
else:
|
||||||
|
@ -116,7 +117,6 @@ class ColoredLevelFormatter(DatetimeFormatter):
|
||||||
.. warning::
|
.. warning::
|
||||||
This is an experimental API.
|
This is an experimental API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert self._fmt is not None
|
assert self._fmt is not None
|
||||||
levelname_fmt_match = self.LEVELNAME_FMT_REGEX.search(self._fmt)
|
levelname_fmt_match = self.LEVELNAME_FMT_REGEX.search(self._fmt)
|
||||||
if not levelname_fmt_match:
|
if not levelname_fmt_match:
|
||||||
|
@ -183,7 +183,6 @@ class PercentStyleMultiline(logging.PercentStyle):
|
||||||
0 (auto-indent turned off) or
|
0 (auto-indent turned off) or
|
||||||
>0 (explicitly set indentation position).
|
>0 (explicitly set indentation position).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if auto_indent_option is None:
|
if auto_indent_option is None:
|
||||||
return 0
|
return 0
|
||||||
elif isinstance(auto_indent_option, bool):
|
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:
|
except ValueError as e:
|
||||||
# Python logging does not recognise this as a logging level
|
# Python logging does not recognise this as a logging level
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
"'{}' is not recognized as a logging level name for "
|
f"'{log_level}' is not recognized as a logging level name for "
|
||||||
"'{}'. Please consider passing the "
|
f"'{setting_name}'. Please consider passing the "
|
||||||
"logging level num instead.".format(log_level, setting_name)
|
"logging level num instead."
|
||||||
) from e
|
) from e
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,8 @@ import fnmatch
|
||||||
import functools
|
import functools
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import warnings
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
from typing import AbstractSet
|
from typing import AbstractSet
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -23,11 +22,12 @@ from typing import overload
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pluggy
|
import pluggy
|
||||||
|
|
||||||
import _pytest._code
|
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
|
import _pytest._code
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import directory_arg
|
from _pytest.config import directory_arg
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
@ -723,12 +723,14 @@ class Session(nodes.Collector):
|
||||||
@overload
|
@overload
|
||||||
def perform_collect(
|
def perform_collect(
|
||||||
self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ...
|
self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ...
|
||||||
) -> Sequence[nodes.Item]: ...
|
) -> Sequence[nodes.Item]:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def perform_collect( # noqa: F811
|
def perform_collect( # noqa: F811
|
||||||
self, args: Optional[Sequence[str]] = ..., genitems: bool = ...
|
self, args: Optional[Sequence[str]] = ..., genitems: bool = ...
|
||||||
) -> Sequence[Union[nodes.Item, nodes.Collector]]: ...
|
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
|
||||||
|
...
|
||||||
|
|
||||||
def perform_collect( # noqa: F811
|
def perform_collect( # noqa: F811
|
||||||
self, args: Optional[Sequence[str]] = None, genitems: bool = True
|
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.config.argparsing import Parser
|
||||||
from _pytest.stash import StashKey
|
from _pytest.stash import StashKey
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest.nodes import Item
|
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, ""):
|
if empty_parameterset not in ("skip", "xfail", "fail_at_collect", None, ""):
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
"{!s} must be one of skip, xfail or fail_at_collect"
|
f"{EMPTY_PARAMETERSET_OPTION!s} must be one of skip, xfail or fail_at_collect"
|
||||||
" but it is {!r}".format(EMPTY_PARAMETERSET_OPTION, empty_parameterset)
|
f" but it is {empty_parameterset!r}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ from typing import NoReturn
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Expression",
|
"Expression",
|
||||||
"ParseError",
|
"ParseError",
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import collections.abc
|
import collections.abc
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import inspect
|
import inspect
|
||||||
import warnings
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Collection
|
from typing import Collection
|
||||||
|
@ -21,6 +20,7 @@ from typing import Type
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
from .._code import getfslineno
|
from .._code import getfslineno
|
||||||
from ..compat import ascii_escaped
|
from ..compat import ascii_escaped
|
||||||
|
@ -32,6 +32,7 @@ from _pytest.deprecated import MARKED_FIXTURE
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
from _pytest.warning_types import PytestUnknownMarkWarning
|
from _pytest.warning_types import PytestUnknownMarkWarning
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..nodes import Node
|
from ..nodes import Node
|
||||||
|
|
||||||
|
@ -111,7 +112,6 @@ class ParameterSet(NamedTuple):
|
||||||
Enforce tuple wrapping so single argument tuple values
|
Enforce tuple wrapping so single argument tuple values
|
||||||
don't get decomposed and break tests.
|
don't get decomposed and break tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(parameterset, cls):
|
if isinstance(parameterset, cls):
|
||||||
return parameterset
|
return parameterset
|
||||||
if force_tuple:
|
if force_tuple:
|
||||||
|
@ -271,8 +271,8 @@ class MarkDecorator:
|
||||||
|
|
||||||
``MarkDecorators`` are created with ``pytest.mark``::
|
``MarkDecorators`` are created with ``pytest.mark``::
|
||||||
|
|
||||||
mark1 = pytest.mark.NAME # Simple MarkDecorator
|
mark1 = pytest.mark.NAME # Simple MarkDecorator
|
||||||
mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator
|
mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator
|
||||||
|
|
||||||
and can then be applied as decorators to test functions::
|
and can then be applied as decorators to test functions::
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ def get_unpacked_marks(
|
||||||
|
|
||||||
|
|
||||||
def normalize_mark_list(
|
def normalize_mark_list(
|
||||||
mark_list: Iterable[Union[Mark, MarkDecorator]]
|
mark_list: Iterable[Union[Mark, MarkDecorator]],
|
||||||
) -> Iterable[Mark]:
|
) -> Iterable[Mark]:
|
||||||
"""
|
"""
|
||||||
Normalize an iterable of Mark or MarkDecorator objects into a list of marks
|
Normalize an iterable of Mark or MarkDecorator objects into a list of marks
|
||||||
|
@ -433,10 +433,12 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
class _SkipMarkDecorator(MarkDecorator):
|
class _SkipMarkDecorator(MarkDecorator):
|
||||||
@overload # type: ignore[override,misc,no-overload-impl]
|
@overload # type: ignore[override,misc,no-overload-impl]
|
||||||
def __call__(self, arg: Markable) -> Markable: ...
|
def __call__(self, arg: Markable) -> Markable:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __call__(self, reason: str = ...) -> "MarkDecorator": ...
|
def __call__(self, reason: str = ...) -> "MarkDecorator":
|
||||||
|
...
|
||||||
|
|
||||||
class _SkipifMarkDecorator(MarkDecorator):
|
class _SkipifMarkDecorator(MarkDecorator):
|
||||||
def __call__( # type: ignore[override]
|
def __call__( # type: ignore[override]
|
||||||
|
@ -444,11 +446,13 @@ if TYPE_CHECKING:
|
||||||
condition: Union[str, bool] = ...,
|
condition: Union[str, bool] = ...,
|
||||||
*conditions: Union[str, bool],
|
*conditions: Union[str, bool],
|
||||||
reason: str = ...,
|
reason: str = ...,
|
||||||
) -> MarkDecorator: ...
|
) -> MarkDecorator:
|
||||||
|
...
|
||||||
|
|
||||||
class _XfailMarkDecorator(MarkDecorator):
|
class _XfailMarkDecorator(MarkDecorator):
|
||||||
@overload # type: ignore[override,misc,no-overload-impl]
|
@overload # type: ignore[override,misc,no-overload-impl]
|
||||||
def __call__(self, arg: Markable) -> Markable: ...
|
def __call__(self, arg: Markable) -> Markable:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def __call__(
|
def __call__(
|
||||||
|
@ -461,7 +465,8 @@ if TYPE_CHECKING:
|
||||||
None, Type[BaseException], Tuple[Type[BaseException], ...]
|
None, Type[BaseException], Tuple[Type[BaseException], ...]
|
||||||
] = ...,
|
] = ...,
|
||||||
strict: bool = ...,
|
strict: bool = ...,
|
||||||
) -> MarkDecorator: ...
|
) -> MarkDecorator:
|
||||||
|
...
|
||||||
|
|
||||||
class _ParametrizeMarkDecorator(MarkDecorator):
|
class _ParametrizeMarkDecorator(MarkDecorator):
|
||||||
def __call__( # type: ignore[override]
|
def __call__( # type: ignore[override]
|
||||||
|
@ -477,7 +482,8 @@ if TYPE_CHECKING:
|
||||||
]
|
]
|
||||||
] = ...,
|
] = ...,
|
||||||
scope: Optional[_ScopeName] = ...,
|
scope: Optional[_ScopeName] = ...,
|
||||||
) -> MarkDecorator: ...
|
) -> MarkDecorator:
|
||||||
|
...
|
||||||
|
|
||||||
class _UsefixturesMarkDecorator(MarkDecorator):
|
class _UsefixturesMarkDecorator(MarkDecorator):
|
||||||
def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override]
|
def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override]
|
||||||
|
@ -497,9 +503,10 @@ class MarkGenerator:
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.slowtest
|
@pytest.mark.slowtest
|
||||||
def test_function():
|
def test_function():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
applies a 'slowtest' :class:`Mark` on ``test_function``.
|
applies a 'slowtest' :class:`Mark` on ``test_function``.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
"""Monkeypatching and mocking functionality."""
|
"""Monkeypatching and mocking functionality."""
|
||||||
|
|
||||||
|
from contextlib import contextmanager
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
|
||||||
from contextlib import contextmanager
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import final
|
from typing import final
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
@ -16,10 +15,12 @@ from typing import overload
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
from _pytest.fixtures import fixture
|
from _pytest.fixtures import fixture
|
||||||
from _pytest.warning_types import PytestWarning
|
from _pytest.warning_types import PytestWarning
|
||||||
|
|
||||||
|
|
||||||
RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$")
|
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)
|
obj = getattr(obj, name)
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
raise AttributeError(
|
raise AttributeError(
|
||||||
"{!r} object at {} has no attribute {!r}".format(
|
f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}"
|
||||||
type(obj).__name__, ann, name
|
|
||||||
)
|
|
||||||
) from e
|
) from e
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
@ -142,7 +141,6 @@ class MonkeyPatch:
|
||||||
which undoes any patching done inside the ``with`` block upon exit.
|
which undoes any patching done inside the ``with`` block upon exit.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
@ -169,7 +167,8 @@ class MonkeyPatch:
|
||||||
name: object,
|
name: object,
|
||||||
value: Notset = ...,
|
value: Notset = ...,
|
||||||
raising: bool = ...,
|
raising: bool = ...,
|
||||||
) -> None: ...
|
) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def setattr(
|
def setattr(
|
||||||
|
@ -178,7 +177,8 @@ class MonkeyPatch:
|
||||||
name: str,
|
name: str,
|
||||||
value: object,
|
value: object,
|
||||||
raising: bool = ...,
|
raising: bool = ...,
|
||||||
) -> None: ...
|
) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
def setattr(
|
def setattr(
|
||||||
self,
|
self,
|
||||||
|
@ -320,10 +320,8 @@ class MonkeyPatch:
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
warnings.warn( # type: ignore[unreachable]
|
warnings.warn( # type: ignore[unreachable]
|
||||||
PytestWarning(
|
PytestWarning(
|
||||||
"Value of environment variable {name} type should be str, but got "
|
f"Value of environment variable {name} type should be str, but got "
|
||||||
"{value!r} (type: {type}); converted to str implicitly".format(
|
f"{value!r} (type: {type(value).__name__}); converted to str implicitly"
|
||||||
name=name, value=value, type=type(value).__name__
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
|
@ -343,7 +341,6 @@ class MonkeyPatch:
|
||||||
|
|
||||||
def syspath_prepend(self, path) -> None:
|
def syspath_prepend(self, path) -> None:
|
||||||
"""Prepend ``path`` to ``sys.path`` list of import locations."""
|
"""Prepend ``path`` to ``sys.path`` list of import locations."""
|
||||||
|
|
||||||
if self._savesyspath is None:
|
if self._savesyspath is None:
|
||||||
self._savesyspath = sys.path[:]
|
self._savesyspath = sys.path[:]
|
||||||
sys.path.insert(0, str(path))
|
sys.path.insert(0, str(path))
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import abc
|
import abc
|
||||||
import os
|
|
||||||
import pathlib
|
|
||||||
import warnings
|
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from inspect import signature
|
from inspect import signature
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -20,6 +19,7 @@ from typing import Type
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pluggy
|
import pluggy
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ from _pytest.pathlib import commonpath
|
||||||
from _pytest.stash import Stash
|
from _pytest.stash import Stash
|
||||||
from _pytest.warning_types import PytestWarning
|
from _pytest.warning_types import PytestWarning
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
# Imported here due to circular import.
|
# Imported here due to circular import.
|
||||||
from _pytest._code.code import _TracebackStyle
|
from _pytest._code.code import _TracebackStyle
|
||||||
|
@ -306,9 +307,7 @@ class Node(abc.ABC, metaclass=NodeMeta):
|
||||||
# enforce type checks here to avoid getting a generic type error later otherwise.
|
# enforce type checks here to avoid getting a generic type error later otherwise.
|
||||||
if not isinstance(warning, Warning):
|
if not isinstance(warning, Warning):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"warning must be an instance of Warning or subclass, got {!r}".format(
|
f"warning must be an instance of Warning or subclass, got {warning!r}"
|
||||||
warning
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
path, lineno = get_fslocation_from_item(self)
|
path, lineno = get_fslocation_from_item(self)
|
||||||
assert lineno is not None
|
assert lineno is not None
|
||||||
|
@ -395,10 +394,12 @@ class Node(abc.ABC, metaclass=NodeMeta):
|
||||||
yield node, mark
|
yield node, mark
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def get_closest_marker(self, name: str) -> Optional[Mark]: ...
|
def get_closest_marker(self, name: str) -> Optional[Mark]:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@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(
|
def get_closest_marker(
|
||||||
self, name: str, default: Optional[Mark] = None
|
self, name: str, default: Optional[Mark] = None
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
functions creating them."""
|
functions creating them."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
@ -11,6 +10,7 @@ from typing import Optional
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
import warnings
|
||||||
|
|
||||||
from _pytest.deprecated import KEYWORD_MSG_ARG
|
from _pytest.deprecated import KEYWORD_MSG_ARG
|
||||||
|
|
||||||
|
@ -297,8 +297,7 @@ def importorskip(
|
||||||
|
|
||||||
if verattr is None or Version(verattr) < Version(minversion):
|
if verattr is None or Version(verattr) < Version(minversion):
|
||||||
raise Skipped(
|
raise Skipped(
|
||||||
"module %r has __version__ %r, required is: %r"
|
f"module {modname!r} has __version__ {verattr!r}, required is: {minversion!r}",
|
||||||
% (modname, verattr, minversion),
|
|
||||||
allow_module_level=True,
|
allow_module_level=True,
|
||||||
)
|
)
|
||||||
return mod
|
return mod
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
"""Submit failure or test session information to a pastebin service."""
|
"""Submit failure or test session information to a pastebin service."""
|
||||||
|
|
||||||
import tempfile
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
import tempfile
|
||||||
from typing import IO
|
from typing import IO
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import create_terminal_writer
|
from _pytest.config import create_terminal_writer
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.stash import StashKey
|
from _pytest.stash import StashKey
|
||||||
from _pytest.terminal import TerminalReporter
|
from _pytest.terminal import TerminalReporter
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
pastebinfile_key = StashKey[IO[bytes]]()
|
pastebinfile_key = StashKey[IO[bytes]]()
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
import atexit
|
import atexit
|
||||||
import contextlib
|
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 enum import Enum
|
||||||
from errno import EBADF
|
from errno import EBADF
|
||||||
from errno import ELOOP
|
from errno import ELOOP
|
||||||
from errno import ENOENT
|
from errno import ENOENT
|
||||||
from errno import ENOTDIR
|
from errno import ENOTDIR
|
||||||
|
import fnmatch
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
import importlib.util
|
||||||
|
import itertools
|
||||||
|
import os
|
||||||
from os.path import expanduser
|
from os.path import expanduser
|
||||||
from os.path import expandvars
|
from os.path import expandvars
|
||||||
from os.path import isabs
|
from os.path import isabs
|
||||||
|
@ -22,6 +17,9 @@ from os.path import sep
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pathlib import PurePath
|
from pathlib import PurePath
|
||||||
from posixpath import sep as posix_sep
|
from posixpath import sep as posix_sep
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -34,11 +32,14 @@ from typing import Tuple
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import uuid
|
||||||
|
import warnings
|
||||||
|
|
||||||
from _pytest.compat import assert_never
|
from _pytest.compat import assert_never
|
||||||
from _pytest.outcomes import skip
|
from _pytest.outcomes import skip
|
||||||
from _pytest.warning_types import PytestWarning
|
from _pytest.warning_types import PytestWarning
|
||||||
|
|
||||||
|
|
||||||
LOCK_TIMEOUT = 60 * 60 * 24 * 3
|
LOCK_TIMEOUT = 60 * 60 * 24 * 3
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,9 +102,7 @@ def on_rm_rf_error(
|
||||||
if func not in (os.open,):
|
if func not in (os.open,):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
PytestWarning(
|
PytestWarning(
|
||||||
"(rm_rf) unknown function {} when removing {}:\n{}: {}".format(
|
f"(rm_rf) unknown function {func} when removing {path}:\n{type(exc)}: {exc}"
|
||||||
func, path, type(exc), exc
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
@ -242,7 +241,7 @@ def make_numbered_dir(root: Path, prefix: str, mode: int = 0o700) -> Path:
|
||||||
else:
|
else:
|
||||||
raise OSError(
|
raise OSError(
|
||||||
"could not create numbered dir with prefix "
|
"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 collections.abc
|
||||||
import contextlib
|
import contextlib
|
||||||
|
from fnmatch import fnmatch
|
||||||
import gc
|
import gc
|
||||||
import importlib
|
import importlib
|
||||||
|
from io import StringIO
|
||||||
import locale
|
import locale
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from fnmatch import fnmatch
|
|
||||||
from io import StringIO
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -70,6 +70,7 @@ from _pytest.reports import TestReport
|
||||||
from _pytest.tmpdir import TempPathFactory
|
from _pytest.tmpdir import TempPathFactory
|
||||||
from _pytest.warning_types import PytestWarning
|
from _pytest.warning_types import PytestWarning
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import pexpect
|
import pexpect
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ class LsofFdLeakChecker:
|
||||||
"*** After:",
|
"*** After:",
|
||||||
*(str(f) for f in lines2),
|
*(str(f) for f in lines2),
|
||||||
"***** %s FD leakage detected" % len(leaked_files),
|
"***** %s FD leakage detected" % len(leaked_files),
|
||||||
"*** function %s:%s: %s " % item.location,
|
"*** function {}:{}: {} ".format(*item.location),
|
||||||
"See issue #2366",
|
"See issue #2366",
|
||||||
]
|
]
|
||||||
item.warn(PytestWarning("\n".join(error)))
|
item.warn(PytestWarning("\n".join(error)))
|
||||||
|
@ -244,7 +245,8 @@ class RecordedHookCall:
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
# The class has undetermined attributes, this tells mypy about it.
|
# The class has undetermined attributes, this tells mypy about it.
|
||||||
def __getattr__(self, key: str): ...
|
def __getattr__(self, key: str):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
@final
|
@final
|
||||||
|
@ -325,13 +327,15 @@ class HookRecorder:
|
||||||
def getreports(
|
def getreports(
|
||||||
self,
|
self,
|
||||||
names: "Literal['pytest_collectreport']",
|
names: "Literal['pytest_collectreport']",
|
||||||
) -> Sequence[CollectReport]: ...
|
) -> Sequence[CollectReport]:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def getreports(
|
def getreports(
|
||||||
self,
|
self,
|
||||||
names: "Literal['pytest_runtest_logreport']",
|
names: "Literal['pytest_runtest_logreport']",
|
||||||
) -> Sequence[TestReport]: ...
|
) -> Sequence[TestReport]:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def getreports(
|
def getreports(
|
||||||
|
@ -340,7 +344,8 @@ class HookRecorder:
|
||||||
"pytest_collectreport",
|
"pytest_collectreport",
|
||||||
"pytest_runtest_logreport",
|
"pytest_runtest_logreport",
|
||||||
),
|
),
|
||||||
) -> Sequence[Union[CollectReport, TestReport]]: ...
|
) -> Sequence[Union[CollectReport, TestReport]]:
|
||||||
|
...
|
||||||
|
|
||||||
def getreports(
|
def getreports(
|
||||||
self,
|
self,
|
||||||
|
@ -372,14 +377,12 @@ class HookRecorder:
|
||||||
values.append(rep)
|
values.append(rep)
|
||||||
if not values:
|
if not values:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"could not find test report matching %r: "
|
f"could not find test report matching {inamepart!r}: "
|
||||||
"no test reports at all!" % (inamepart,)
|
"no test reports at all!"
|
||||||
)
|
)
|
||||||
if len(values) > 1:
|
if len(values) > 1:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"found 2 or more testreports matching {!r}: {}".format(
|
f"found 2 or more testreports matching {inamepart!r}: {values}"
|
||||||
inamepart, values
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return values[0]
|
return values[0]
|
||||||
|
|
||||||
|
@ -387,13 +390,15 @@ class HookRecorder:
|
||||||
def getfailures(
|
def getfailures(
|
||||||
self,
|
self,
|
||||||
names: "Literal['pytest_collectreport']",
|
names: "Literal['pytest_collectreport']",
|
||||||
) -> Sequence[CollectReport]: ...
|
) -> Sequence[CollectReport]:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def getfailures(
|
def getfailures(
|
||||||
self,
|
self,
|
||||||
names: "Literal['pytest_runtest_logreport']",
|
names: "Literal['pytest_runtest_logreport']",
|
||||||
) -> Sequence[TestReport]: ...
|
) -> Sequence[TestReport]:
|
||||||
|
...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def getfailures(
|
def getfailures(
|
||||||
|
@ -402,7 +407,8 @@ class HookRecorder:
|
||||||
"pytest_collectreport",
|
"pytest_collectreport",
|
||||||
"pytest_runtest_logreport",
|
"pytest_runtest_logreport",
|
||||||
),
|
),
|
||||||
) -> Sequence[Union[CollectReport, TestReport]]: ...
|
) -> Sequence[Union[CollectReport, TestReport]]:
|
||||||
|
...
|
||||||
|
|
||||||
def getfailures(
|
def getfailures(
|
||||||
self,
|
self,
|
||||||
|
@ -801,7 +807,6 @@ class Pytester:
|
||||||
The first created file.
|
The first created file.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
pytester.makefile(".txt", "line1", "line2")
|
pytester.makefile(".txt", "line1", "line2")
|
||||||
|
@ -855,7 +860,6 @@ class Pytester:
|
||||||
existing files.
|
existing files.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def test_something(pytester):
|
def test_something(pytester):
|
||||||
|
@ -875,7 +879,6 @@ class Pytester:
|
||||||
existing files.
|
existing files.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def test_something(pytester):
|
def test_something(pytester):
|
||||||
|
@ -1265,9 +1268,7 @@ class Pytester:
|
||||||
for item in items:
|
for item in items:
|
||||||
if item.name == funcname:
|
if item.name == funcname:
|
||||||
return item
|
return item
|
||||||
assert 0, "{!r} item not found in module:\n{}\nitems: {}".format(
|
assert 0, f"{funcname!r} item not found in module:\n{source}\nitems: {items}"
|
||||||
funcname, source, items
|
|
||||||
)
|
|
||||||
|
|
||||||
def getitems(self, source: Union[str, "os.PathLike[str]"]) -> List[Item]:
|
def getitems(self, source: Union[str, "os.PathLike[str]"]) -> List[Item]:
|
||||||
"""Return all test items collected from the module.
|
"""Return all test items collected from the module.
|
||||||
|
@ -1426,10 +1427,7 @@ class Pytester:
|
||||||
def handle_timeout() -> None:
|
def handle_timeout() -> None:
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
|
||||||
timeout_message = (
|
timeout_message = f"{timeout} second timeout expired running: {cmdargs}"
|
||||||
"{seconds} second timeout expired running:"
|
|
||||||
" {command}".format(seconds=timeout, command=cmdargs)
|
|
||||||
)
|
|
||||||
|
|
||||||
popen.kill()
|
popen.kill()
|
||||||
popen.wait()
|
popen.wait()
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
"""Python test discovery, setup and run of test functions."""
|
"""Python test discovery, setup and run of test functions."""
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
from collections import Counter
|
||||||
|
from collections import defaultdict
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import enum
|
import enum
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
from functools import partial
|
||||||
import inspect
|
import inspect
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
import warnings
|
|
||||||
from collections import Counter
|
|
||||||
from collections import defaultdict
|
|
||||||
from functools import partial
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
@ -30,6 +29,7 @@ from typing import Sequence
|
||||||
from typing import Set
|
from typing import Set
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
from _pytest import fixtures
|
from _pytest import fixtures
|
||||||
|
@ -85,6 +85,7 @@ from _pytest.warning_types import PytestCollectionWarning
|
||||||
from _pytest.warning_types import PytestReturnNotNoneWarning
|
from _pytest.warning_types import PytestReturnNotNoneWarning
|
||||||
from _pytest.warning_types import PytestUnhandledCoroutineWarning
|
from _pytest.warning_types import PytestUnhandledCoroutineWarning
|
||||||
|
|
||||||
|
|
||||||
_PYTEST_DIR = Path(_pytest.__file__).parent
|
_PYTEST_DIR = Path(_pytest.__file__).parent
|
||||||
|
|
||||||
|
|
||||||
|
@ -267,8 +268,8 @@ def pytest_pycollect_makeitem(
|
||||||
elif getattr(obj, "__test__", True):
|
elif getattr(obj, "__test__", True):
|
||||||
if is_generator(obj):
|
if is_generator(obj):
|
||||||
res: Function = Function.from_parent(collector, name=name)
|
res: Function = Function.from_parent(collector, name=name)
|
||||||
reason = "yield tests were removed in pytest 4.0 - {name} will be ignored".format(
|
reason = (
|
||||||
name=name
|
f"yield tests were removed in pytest 4.0 - {name} will be ignored"
|
||||||
)
|
)
|
||||||
res.add_marker(MARK_GEN.xfail(run=False, reason=reason))
|
res.add_marker(MARK_GEN.xfail(run=False, reason=reason))
|
||||||
res.warn(PytestCollectionWarning(reason))
|
res.warn(PytestCollectionWarning(reason))
|
||||||
|
@ -560,10 +561,10 @@ def importtestmodule(
|
||||||
)
|
)
|
||||||
formatted_tb = str(exc_repr)
|
formatted_tb = str(exc_repr)
|
||||||
raise nodes.Collector.CollectError(
|
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"
|
"Hint: make sure your test modules/packages have valid Python names.\n"
|
||||||
"Traceback:\n"
|
"Traceback:\n"
|
||||||
"{traceback}".format(path=path, traceback=formatted_tb)
|
f"{formatted_tb}"
|
||||||
) from e
|
) from e
|
||||||
except skip.Exception as e:
|
except skip.Exception as e:
|
||||||
if e.allow_module_level:
|
if e.allow_module_level:
|
||||||
|
@ -1496,17 +1497,13 @@ class Metafunc:
|
||||||
for arg in indirect:
|
for arg in indirect:
|
||||||
if arg not in argnames:
|
if arg not in argnames:
|
||||||
fail(
|
fail(
|
||||||
"In {}: indirect fixture '{}' doesn't exist".format(
|
f"In {self.function.__name__}: indirect fixture '{arg}' doesn't exist",
|
||||||
self.function.__name__, arg
|
|
||||||
),
|
|
||||||
pytrace=False,
|
pytrace=False,
|
||||||
)
|
)
|
||||||
arg_directness[arg] = "indirect"
|
arg_directness[arg] = "indirect"
|
||||||
else:
|
else:
|
||||||
fail(
|
fail(
|
||||||
"In {func}: expected Sequence or boolean for indirect, got {type}".format(
|
f"In {self.function.__name__}: expected Sequence or boolean for indirect, got {type(indirect).__name__}",
|
||||||
type=type(indirect).__name__, func=self.function.__name__
|
|
||||||
),
|
|
||||||
pytrace=False,
|
pytrace=False,
|
||||||
)
|
)
|
||||||
return arg_directness
|
return arg_directness
|
||||||
|
@ -1528,9 +1525,7 @@ class Metafunc:
|
||||||
if arg not in self.fixturenames:
|
if arg not in self.fixturenames:
|
||||||
if arg in default_arg_names:
|
if arg in default_arg_names:
|
||||||
fail(
|
fail(
|
||||||
"In {}: function already takes an argument '{}' with a default value".format(
|
f"In {func_name}: function already takes an argument '{arg}' with a default value",
|
||||||
func_name, arg
|
|
||||||
),
|
|
||||||
pytrace=False,
|
pytrace=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import math
|
|
||||||
import pprint
|
|
||||||
from collections.abc import Collection
|
from collections.abc import Collection
|
||||||
from collections.abc import Sized
|
from collections.abc import Sized
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
import math
|
||||||
from numbers import Complex
|
from numbers import Complex
|
||||||
|
import pprint
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -26,6 +26,7 @@ import _pytest._code
|
||||||
from _pytest.compat import STRING_TYPES
|
from _pytest.compat import STRING_TYPES
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from numpy import ndarray
|
from numpy import ndarray
|
||||||
|
|
||||||
|
@ -237,9 +238,7 @@ class ApproxMapping(ApproxBase):
|
||||||
with numeric values (the keys can be anything)."""
|
with numeric values (the keys can be anything)."""
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "approx({!r})".format(
|
return f"approx({({k: self._approx_scalar(v) for k, v in self.expected.items()})!r})"
|
||||||
{k: self._approx_scalar(v) for k, v in self.expected.items()}
|
|
||||||
)
|
|
||||||
|
|
||||||
def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]:
|
def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]:
|
||||||
import math
|
import math
|
||||||
|
@ -314,9 +313,7 @@ class ApproxSequenceLike(ApproxBase):
|
||||||
seq_type = type(self.expected)
|
seq_type = type(self.expected)
|
||||||
if seq_type not in (tuple, list):
|
if seq_type not in (tuple, list):
|
||||||
seq_type = list
|
seq_type = list
|
||||||
return "approx({!r})".format(
|
return f"approx({seq_type(self._approx_scalar(x) for x in self.expected)!r})"
|
||||||
seq_type(self._approx_scalar(x) for x in self.expected)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _repr_compare(self, other_side: Sequence[float]) -> List[str]:
|
def _repr_compare(self, other_side: Sequence[float]) -> List[str]:
|
||||||
import math
|
import math
|
||||||
|
@ -696,7 +693,6 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase:
|
||||||
``approx`` falls back to strict equality for nonnumeric types instead
|
``approx`` falls back to strict equality for nonnumeric types instead
|
||||||
of raising ``TypeError``.
|
of raising ``TypeError``.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Delegate the comparison to a class that knows how to deal with the type
|
# 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).
|
# of the expected value (e.g. int, float, list, dict, numpy.array, etc).
|
||||||
#
|
#
|
||||||
|
@ -778,7 +774,8 @@ def raises(
|
||||||
expected_exception: Union[Type[E], Tuple[Type[E], ...]],
|
expected_exception: Union[Type[E], Tuple[Type[E], ...]],
|
||||||
*,
|
*,
|
||||||
match: Optional[Union[str, Pattern[str]]] = ...,
|
match: Optional[Union[str, Pattern[str]]] = ...,
|
||||||
) -> "RaisesContext[E]": ...
|
) -> "RaisesContext[E]":
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
|
@ -787,7 +784,8 @@ def raises( # noqa: F811
|
||||||
func: Callable[..., Any],
|
func: Callable[..., Any],
|
||||||
*args: Any,
|
*args: Any,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> _pytest._code.ExceptionInfo[E]: ...
|
) -> _pytest._code.ExceptionInfo[E]:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
def raises( # noqa: F811
|
def raises( # noqa: F811
|
||||||
|
@ -836,10 +834,10 @@ def raises( # noqa: F811
|
||||||
The ``match`` argument searches the formatted exception string, which includes any
|
The ``match`` argument searches the formatted exception string, which includes any
|
||||||
`PEP-678 <https://peps.python.org/pep-0678/>`__ ``__notes__``:
|
`PEP-678 <https://peps.python.org/pep-0678/>`__ ``__notes__``:
|
||||||
|
|
||||||
>>> with pytest.raises(ValueError, match=r'had a note added'): # doctest: +SKIP
|
>>> with pytest.raises(ValueError, match=r"had a note added"): # doctest: +SKIP
|
||||||
... e = ValueError("value must be 42")
|
... e = ValueError("value must be 42")
|
||||||
... e.add_note("had a note added")
|
... e.add_note("had a note added")
|
||||||
... raise e
|
... raise e
|
||||||
|
|
||||||
The context manager produces an :class:`ExceptionInfo` object which can be used to inspect the
|
The context manager produces an :class:`ExceptionInfo` object which can be used to inspect the
|
||||||
details of the captured exception::
|
details of the captured exception::
|
||||||
|
@ -854,7 +852,7 @@ def raises( # noqa: F811
|
||||||
Given that ``pytest.raises`` matches subclasses, be wary of using it to match :class:`Exception` like this::
|
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.
|
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
|
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
|
real bugs, where the user wrote this expecting a specific exception, but some other exception is being
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
"""Record warnings during test function execution."""
|
"""Record warnings during test function execution."""
|
||||||
|
|
||||||
import re
|
|
||||||
import warnings
|
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
|
import re
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -17,12 +16,14 @@ from typing import Tuple
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
from _pytest.deprecated import check_ispytest
|
from _pytest.deprecated import check_ispytest
|
||||||
from _pytest.deprecated import WARNS_NONE_ARG
|
from _pytest.deprecated import WARNS_NONE_ARG
|
||||||
from _pytest.fixtures import fixture
|
from _pytest.fixtures import fixture
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,13 +43,15 @@ def recwarn() -> Generator["WarningsRecorder", None, None]:
|
||||||
@overload
|
@overload
|
||||||
def deprecated_call(
|
def deprecated_call(
|
||||||
*, match: Optional[Union[str, Pattern[str]]] = ...
|
*, match: Optional[Union[str, Pattern[str]]] = ...
|
||||||
) -> "WarningsRecorder": ...
|
) -> "WarningsRecorder":
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def deprecated_call( # noqa: F811
|
def deprecated_call( # noqa: F811
|
||||||
func: Callable[..., T], *args: Any, **kwargs: Any
|
func: Callable[..., T], *args: Any, **kwargs: Any
|
||||||
) -> T: ...
|
) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
def deprecated_call( # noqa: F811
|
def deprecated_call( # noqa: F811
|
||||||
|
@ -90,7 +93,8 @@ def warns(
|
||||||
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ...,
|
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ...,
|
||||||
*,
|
*,
|
||||||
match: Optional[Union[str, Pattern[str]]] = ...,
|
match: Optional[Union[str, Pattern[str]]] = ...,
|
||||||
) -> "WarningsChecker": ...
|
) -> "WarningsChecker":
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
|
@ -99,7 +103,8 @@ def warns( # noqa: F811
|
||||||
func: Callable[..., T],
|
func: Callable[..., T],
|
||||||
*args: Any,
|
*args: Any,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> T: ...
|
) -> T:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
def warns( # noqa: F811
|
def warns( # noqa: F811
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import os
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
import os
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
@ -36,6 +36,7 @@ from _pytest.nodes import Collector
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
from _pytest.outcomes import skip
|
from _pytest.outcomes import skip
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest.runner import CallInfo
|
from _pytest.runner import CallInfo
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ def getworkerinfoline(node):
|
||||||
return node._workerinfocache
|
return node._workerinfocache
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
d = node.workerinfo
|
d = node.workerinfo
|
||||||
ver = "%s.%s.%s" % d["version_info"][:3]
|
ver = "{}.{}.{}".format(*d["version_info"][:3])
|
||||||
node._workerinfocache = s = "[{}] {} -- Python {} {}".format(
|
node._workerinfocache = s = "[{}] {} -- Python {} {}".format(
|
||||||
d["id"], d["sysplatform"], ver, d["executable"]
|
d["id"], d["sysplatform"], ver, d["executable"]
|
||||||
)
|
)
|
||||||
|
@ -70,7 +71,8 @@ class BaseReport:
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
# Can have arbitrary fields given to __init__().
|
# 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:
|
def toterminal(self, out: TerminalWriter) -> None:
|
||||||
if hasattr(self, "node"):
|
if hasattr(self, "node"):
|
||||||
|
@ -312,9 +314,7 @@ class TestReport(BaseReport):
|
||||||
self.__dict__.update(extra)
|
self.__dict__.update(extra)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "<{} {!r} when={!r} outcome={!r}>".format(
|
return f"<{self.__class__.__name__} {self.nodeid!r} when={self.when!r} outcome={self.outcome!r}>"
|
||||||
self.__class__.__name__, self.nodeid, self.when, self.outcome
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport":
|
def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport":
|
||||||
|
@ -429,9 +429,7 @@ class CollectReport(BaseReport):
|
||||||
return (self.fspath, None, self.fspath)
|
return (self.fspath, None, self.fspath)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "<CollectReport {!r} lenresult={} outcome={!r}>".format(
|
return f"<CollectReport {self.nodeid!r} lenresult={len(self.result)} outcome={self.outcome!r}>"
|
||||||
self.nodeid, len(self.result), self.outcome
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CollectErrorRepr(TerminalRepr):
|
class CollectErrorRepr(TerminalRepr):
|
||||||
|
@ -443,7 +441,7 @@ class CollectErrorRepr(TerminalRepr):
|
||||||
|
|
||||||
|
|
||||||
def pytest_report_to_serializable(
|
def pytest_report_to_serializable(
|
||||||
report: Union[CollectReport, TestReport]
|
report: Union[CollectReport, TestReport],
|
||||||
) -> Optional[Dict[str, Any]]:
|
) -> Optional[Dict[str, Any]]:
|
||||||
if isinstance(report, (TestReport, CollectReport)):
|
if isinstance(report, (TestReport, CollectReport)):
|
||||||
data = report._to_json()
|
data = report._to_json()
|
||||||
|
@ -475,7 +473,7 @@ def _report_to_json(report: BaseReport) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def serialize_repr_entry(
|
def serialize_repr_entry(
|
||||||
entry: Union[ReprEntry, ReprEntryNative]
|
entry: Union[ReprEntry, ReprEntryNative],
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
data = dataclasses.asdict(entry)
|
data = dataclasses.asdict(entry)
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
|
@ -607,9 +605,9 @@ def _report_kwargs_from_json(reportdict: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
description,
|
description,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = (
|
exception_info: Union[
|
||||||
ExceptionChainRepr(chain)
|
ExceptionChainRepr, ReprExceptionInfo
|
||||||
)
|
] = ExceptionChainRepr(chain)
|
||||||
else:
|
else:
|
||||||
exception_info = ReprExceptionInfo(
|
exception_info = ReprExceptionInfo(
|
||||||
reprtraceback=reprtraceback,
|
reprtraceback=reprtraceback,
|
||||||
|
|
|
@ -37,6 +37,7 @@ from _pytest.outcomes import OutcomeException
|
||||||
from _pytest.outcomes import Skipped
|
from _pytest.outcomes import Skipped
|
||||||
from _pytest.outcomes import TEST_OUTCOME
|
from _pytest.outcomes import TEST_OUTCOME
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[:2] < (3, 11):
|
if sys.version_info[:2] < (3, 11):
|
||||||
from exceptiongroup import BaseExceptionGroup
|
from exceptiongroup import BaseExceptionGroup
|
||||||
|
|
||||||
|
@ -94,8 +95,7 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None:
|
||||||
if verbose < 2 and rep.duration < durations_min:
|
if verbose < 2 and rep.duration < durations_min:
|
||||||
tr.write_line("")
|
tr.write_line("")
|
||||||
tr.write_line(
|
tr.write_line(
|
||||||
"(%s durations < %gs hidden. Use -vv to show these durations.)"
|
f"({len(dlist) - i} durations < {durations_min:g}s hidden. Use -vv to show these durations.)"
|
||||||
% (len(dlist) - i, durations_min)
|
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
tr.write_line(f"{rep.duration:02.2f}s {rep.when:<8} {rep.nodeid}")
|
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 Literal
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
_ScopeName = Literal["session", "package", "module", "class", "function"]
|
_ScopeName = Literal["session", "package", "module", "class", "function"]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ from typing import Generator
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest._io.saferepr import saferepr
|
from _pytest._io.saferepr import saferepr
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
@ -10,6 +9,7 @@ from _pytest.config.argparsing import Parser
|
||||||
from _pytest.fixtures import FixtureDef
|
from _pytest.fixtures import FixtureDef
|
||||||
from _pytest.fixtures import SubRequest
|
from _pytest.fixtures import SubRequest
|
||||||
from _pytest.scope import Scope
|
from _pytest.scope import Scope
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser: Parser) -> None:
|
def pytest_addoption(parser: Parser) -> None:
|
||||||
|
@ -71,7 +71,7 @@ def _show_fixture_action(fixturedef: FixtureDef[object], msg: str) -> None:
|
||||||
scope_indent = list(reversed(Scope)).index(fixturedef._scope)
|
scope_indent = list(reversed(Scope)).index(fixturedef._scope)
|
||||||
tw.write(" " * 2 * scope_indent)
|
tw.write(" " * 2 * scope_indent)
|
||||||
tw.write(
|
tw.write(
|
||||||
"{step} {scope} {fixture}".format(
|
"{step} {scope} {fixture}".format( # noqa: UP032 (Readability)
|
||||||
step=msg.ljust(8), # align the output to TEARDOWN
|
step=msg.ljust(8), # align the output to TEARDOWN
|
||||||
scope=fixturedef.scope[0].upper(),
|
scope=fixturedef.scope[0].upper(),
|
||||||
fixture=fixturedef.argname,
|
fixture=fixturedef.argname,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.fixtures import FixtureDef
|
from _pytest.fixtures import FixtureDef
|
||||||
from _pytest.fixtures import SubRequest
|
from _pytest.fixtures import SubRequest
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser: Parser) -> None:
|
def pytest_addoption(parser: Parser) -> None:
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
"""Support for skip/xfail functions and markers."""
|
"""Support for skip/xfail functions and markers."""
|
||||||
|
|
||||||
|
from collections.abc import Mapping
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from collections.abc import Mapping
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
@ -105,9 +105,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool,
|
||||||
):
|
):
|
||||||
if not isinstance(dictionary, Mapping):
|
if not isinstance(dictionary, Mapping):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"pytest_markeval_namespace() needs to return a dict, got {!r}".format(
|
f"pytest_markeval_namespace() needs to return a dict, got {dictionary!r}"
|
||||||
dictionary
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
globals_.update(dictionary)
|
globals_.update(dictionary)
|
||||||
if hasattr(item, "obj"):
|
if hasattr(item, "obj"):
|
||||||
|
|
|
@ -5,6 +5,7 @@ from typing import Generic
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["Stash", "StashKey"]
|
__all__ = ["Stash", "StashKey"]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,13 @@ from typing import List
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config.argparsing import Parser
|
from _pytest.config.argparsing import Parser
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.reports import TestReport
|
from _pytest.reports import TestReport
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest.cacheprovider import Cache
|
from _pytest.cacheprovider import Cache
|
||||||
|
|
|
@ -4,16 +4,15 @@ This is a good source for looking at the various reporting hooks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
from collections import Counter
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import datetime
|
import datetime
|
||||||
|
from functools import partial
|
||||||
import inspect
|
import inspect
|
||||||
|
from pathlib import Path
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import warnings
|
|
||||||
from collections import Counter
|
|
||||||
from functools import partial
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import ClassVar
|
from typing import ClassVar
|
||||||
|
@ -31,16 +30,17 @@ from typing import TextIO
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pluggy
|
import pluggy
|
||||||
|
|
||||||
import _pytest._version
|
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
from _pytest import timing
|
from _pytest import timing
|
||||||
from _pytest._code import ExceptionInfo
|
from _pytest._code import ExceptionInfo
|
||||||
from _pytest._code.code import ExceptionRepr
|
from _pytest._code.code import ExceptionRepr
|
||||||
from _pytest._io import TerminalWriter
|
from _pytest._io import TerminalWriter
|
||||||
from _pytest._io.wcwidth import wcswidth
|
from _pytest._io.wcwidth import wcswidth
|
||||||
|
import _pytest._version
|
||||||
from _pytest.assertion.util import running_on_ci
|
from _pytest.assertion.util import running_on_ci
|
||||||
from _pytest.config import _PluggyPlugin
|
from _pytest.config import _PluggyPlugin
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
|
@ -55,6 +55,7 @@ from _pytest.reports import BaseReport
|
||||||
from _pytest.reports import CollectReport
|
from _pytest.reports import CollectReport
|
||||||
from _pytest.reports import TestReport
|
from _pytest.reports import TestReport
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
|
|
||||||
|
@ -671,8 +672,8 @@ class TerminalReporter:
|
||||||
return f" [ {collected} / {collected} ]"
|
return f" [ {collected} / {collected} ]"
|
||||||
else:
|
else:
|
||||||
if collected:
|
if collected:
|
||||||
return " [{:3d}%]".format(
|
return (
|
||||||
len(self._progress_nodeids_reported) * 100 // collected
|
f" [{len(self._progress_nodeids_reported) * 100 // collected:3d}%]"
|
||||||
)
|
)
|
||||||
return " [100%]"
|
return " [100%]"
|
||||||
|
|
||||||
|
@ -757,9 +758,7 @@ class TerminalReporter:
|
||||||
if pypy_version_info:
|
if pypy_version_info:
|
||||||
verinfo = ".".join(map(str, pypy_version_info[:3]))
|
verinfo = ".".join(map(str, pypy_version_info[:3]))
|
||||||
msg += f"[pypy-{verinfo}-{pypy_version_info[3]}]"
|
msg += f"[pypy-{verinfo}-{pypy_version_info[3]}]"
|
||||||
msg += ", pytest-{}, pluggy-{}".format(
|
msg += f", pytest-{_pytest._version.version}, pluggy-{pluggy.__version__}"
|
||||||
_pytest._version.version, pluggy.__version__
|
|
||||||
)
|
|
||||||
if (
|
if (
|
||||||
self.verbosity > 0
|
self.verbosity > 0
|
||||||
or self.config.option.debug
|
or self.config.option.debug
|
||||||
|
@ -1464,7 +1463,7 @@ def _plugin_nameversions(plugininfo) -> List[str]:
|
||||||
values: List[str] = []
|
values: List[str] = []
|
||||||
for plugin, dist in plugininfo:
|
for plugin, dist in plugininfo:
|
||||||
# Gets us name and version!
|
# 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.
|
# Questionable convenience, but it keeps things short.
|
||||||
if name.startswith("pytest-"):
|
if name.startswith("pytest-"):
|
||||||
name = name[7:]
|
name = name[7:]
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import warnings
|
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
|
@ -10,4 +10,5 @@ from time import perf_counter
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["perf_counter", "sleep", "time"]
|
__all__ = ["perf_counter", "sleep", "time"]
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import tempfile
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import re
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
|
import tempfile
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import final
|
from typing import final
|
||||||
|
@ -32,6 +32,7 @@ from _pytest.nodes import Item
|
||||||
from _pytest.reports import TestReport
|
from _pytest.reports import TestReport
|
||||||
from _pytest.stash import StashKey
|
from _pytest.stash import StashKey
|
||||||
|
|
||||||
|
|
||||||
tmppath_result_key = StashKey[Dict[str, bool]]()
|
tmppath_result_key = StashKey[Dict[str, bool]]()
|
||||||
RetentionType = Literal["all", "failed", "none"]
|
RetentionType = Literal["all", "failed", "none"]
|
||||||
|
|
||||||
|
@ -268,7 +269,6 @@ def tmp_path(
|
||||||
|
|
||||||
The returned object is a :class:`pathlib.Path` object.
|
The returned object is a :class:`pathlib.Path` object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
path = _mk_tmp(request, tmp_path_factory)
|
path = _mk_tmp(request, tmp_path_factory)
|
||||||
yield path
|
yield path
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ from typing import TYPE_CHECKING
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
|
||||||
from _pytest.compat import getimfunc
|
from _pytest.compat import getimfunc
|
||||||
from _pytest.compat import is_async_function
|
from _pytest.compat import is_async_function
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
|
@ -31,6 +30,8 @@ from _pytest.python import Function
|
||||||
from _pytest.python import Module
|
from _pytest.python import Module
|
||||||
from _pytest.runner import CallInfo
|
from _pytest.runner import CallInfo
|
||||||
from _pytest.scope import Scope
|
from _pytest.scope import Scope
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
import unittest
|
import unittest
|
||||||
|
@ -219,7 +220,9 @@ class TestCaseFunction(Function):
|
||||||
# Unwrap potential exception info (see twisted trial support below).
|
# Unwrap potential exception info (see twisted trial support below).
|
||||||
rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo)
|
rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo)
|
||||||
try:
|
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
|
# Invoke the attributes to trigger storing the traceback
|
||||||
# trial causes some issue there.
|
# trial causes some issue there.
|
||||||
excinfo.value
|
excinfo.value
|
||||||
|
@ -364,9 +367,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None:
|
||||||
# handled internally, and doesn't reach here.
|
# handled internally, and doesn't reach here.
|
||||||
unittest = sys.modules.get("unittest")
|
unittest = sys.modules.get("unittest")
|
||||||
if (
|
if (
|
||||||
unittest
|
unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined]
|
||||||
and call.excinfo
|
|
||||||
and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined]
|
|
||||||
):
|
):
|
||||||
excinfo = call.excinfo
|
excinfo = call.excinfo
|
||||||
call2 = CallInfo[None].from_call(
|
call2 = CallInfo[None].from_call(
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import warnings
|
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Type
|
from typing import Type
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import inspect
|
import inspect
|
||||||
import warnings
|
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import final
|
from typing import final
|
||||||
from typing import Generic
|
from typing import Generic
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
class PytestWarning(UserWarning):
|
class PytestWarning(UserWarning):
|
||||||
|
@ -79,11 +79,7 @@ class PytestExperimentalApiWarning(PytestWarning, FutureWarning):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def simple(cls, apiname: str) -> "PytestExperimentalApiWarning":
|
def simple(cls, apiname: str) -> "PytestExperimentalApiWarning":
|
||||||
return cls(
|
return cls(f"{apiname} is an experimental api that may change over time")
|
||||||
"{apiname} is an experimental api that may change over time".format(
|
|
||||||
apiname=apiname
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@final
|
@final
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import sys
|
|
||||||
import warnings
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
import sys
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
import warnings
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.config import apply_warning_filters
|
from _pytest.config import apply_warning_filters
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import parse_warning_filter
|
from _pytest.config import parse_warning_filter
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.nodes import Item
|
from _pytest.nodes import Item
|
||||||
from _pytest.terminal import TerminalReporter
|
from _pytest.terminal import TerminalReporter
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def pytest_configure(config: Config) -> None:
|
def pytest_configure(config: Config) -> None:
|
||||||
|
|
|
@ -6,6 +6,7 @@ import sys
|
||||||
import _pytest._py.error as error
|
import _pytest._py.error as error
|
||||||
import _pytest._py.path as path
|
import _pytest._py.path as path
|
||||||
|
|
||||||
|
|
||||||
sys.modules["py.error"] = error
|
sys.modules["py.error"] = error
|
||||||
sys.modules["py.path"] = path
|
sys.modules["py.path"] = path
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ from _pytest.warning_types import PytestUnknownMarkWarning
|
||||||
from _pytest.warning_types import PytestUnraisableExceptionWarning
|
from _pytest.warning_types import PytestUnraisableExceptionWarning
|
||||||
from _pytest.warning_types import PytestWarning
|
from _pytest.warning_types import PytestWarning
|
||||||
|
|
||||||
|
|
||||||
set_trace = __pytestPDB.set_trace
|
set_trace = __pytestPDB.set_trace
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
raise SystemExit(pytest.console_main())
|
raise SystemExit(pytest.console_main())
|
||||||
|
|
|
@ -3,8 +3,8 @@ import multiprocessing
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import warnings
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
import warnings
|
||||||
|
|
||||||
from py import error
|
from py import error
|
||||||
from py.path import local
|
from py.path import local
|
||||||
|
@ -182,7 +182,7 @@ class CommonFSTests:
|
||||||
def test_listdir_filter(self, path1):
|
def test_listdir_filter(self, path1):
|
||||||
p = path1.listdir(lambda x: x.check(dir=1))
|
p = path1.listdir(lambda x: x.check(dir=1))
|
||||||
assert path1.join("sampledir") in p
|
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):
|
def test_listdir_sorted(self, path1):
|
||||||
p = path1.listdir(lambda x: x.check(basestarts="sample"), sort=True)
|
p = path1.listdir(lambda x: x.check(basestarts="sample"), sort=True)
|
||||||
|
@ -202,7 +202,7 @@ class CommonFSTests:
|
||||||
for i in path1.visit(None, lambda x: x.basename != "sampledir"):
|
for i in path1.visit(None, lambda x: x.basename != "sampledir"):
|
||||||
lst.append(i.relto(path1))
|
lst.append(i.relto(path1))
|
||||||
assert "sampledir" in lst
|
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(
|
@pytest.mark.parametrize(
|
||||||
"fil",
|
"fil",
|
||||||
|
|
|
@ -5,10 +5,10 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.pathlib import symlink_or_skip
|
from _pytest.pathlib import symlink_or_skip
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def prepend_pythonpath(*dirs) -> str:
|
def prepend_pythonpath(*dirs) -> str:
|
||||||
|
|
|
@ -3,13 +3,13 @@ import sys
|
||||||
from types import FrameType
|
from types import FrameType
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest._code import Code
|
from _pytest._code import Code
|
||||||
from _pytest._code import ExceptionInfo
|
from _pytest._code import ExceptionInfo
|
||||||
from _pytest._code import Frame
|
from _pytest._code import Frame
|
||||||
from _pytest._code import Source
|
from _pytest._code import Source
|
||||||
from _pytest._code.code import ExceptionChainRepr
|
from _pytest._code.code import ExceptionChainRepr
|
||||||
from _pytest._code.code import ReprFuncArgs
|
from _pytest._code.code import ReprFuncArgs
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_ne() -> None:
|
def test_ne() -> None:
|
||||||
|
|
|
@ -3,16 +3,15 @@ from __future__ import annotations
|
||||||
import importlib
|
import importlib
|
||||||
import io
|
import io
|
||||||
import operator
|
import operator
|
||||||
|
from pathlib import Path
|
||||||
import queue
|
import queue
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
|
||||||
from _pytest._code.code import ExceptionChainRepr
|
from _pytest._code.code import ExceptionChainRepr
|
||||||
from _pytest._code.code import ExceptionInfo
|
from _pytest._code.code import ExceptionInfo
|
||||||
from _pytest._code.code import FormattedExcinfo
|
from _pytest._code.code import FormattedExcinfo
|
||||||
|
@ -22,6 +21,8 @@ from _pytest.pathlib import bestrelpath
|
||||||
from _pytest.pathlib import import_path
|
from _pytest.pathlib import import_path
|
||||||
from _pytest.pytester import LineMatcher
|
from _pytest.pytester import LineMatcher
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from _pytest._code.code import _TracebackStyle
|
from _pytest._code.code import _TracebackStyle
|
||||||
|
@ -1172,9 +1173,7 @@ raise ValueError()
|
||||||
"funcargs": funcargs,
|
"funcargs": funcargs,
|
||||||
"tbfilter": tbfilter,
|
"tbfilter": tbfilter,
|
||||||
},
|
},
|
||||||
id="style={},showlocals={},funcargs={},tbfilter={}".format(
|
id=f"style={style},showlocals={showlocals},funcargs={funcargs},tbfilter={tbfilter}",
|
||||||
style, showlocals, funcargs, tbfilter
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
for style in ["long", "short", "line", "no", "native", "value", "auto"]
|
for style in ["long", "short", "line", "no", "native", "value", "auto"]
|
||||||
for showlocals in (True, False)
|
for showlocals in (True, False)
|
||||||
|
@ -1338,7 +1337,7 @@ raise ValueError()
|
||||||
"""
|
"""
|
||||||
raise_suffix = " from None" if mode == "from_none" else ""
|
raise_suffix = " from None" if mode == "from_none" else ""
|
||||||
mod = importasmod(
|
mod = importasmod(
|
||||||
"""
|
f"""
|
||||||
def f():
|
def f():
|
||||||
try:
|
try:
|
||||||
g()
|
g()
|
||||||
|
@ -1346,9 +1345,7 @@ raise ValueError()
|
||||||
raise AttributeError(){raise_suffix}
|
raise AttributeError(){raise_suffix}
|
||||||
def g():
|
def g():
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
""".format(
|
"""
|
||||||
raise_suffix=raise_suffix
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
excinfo = pytest.raises(AttributeError, mod.f)
|
excinfo = pytest.raises(AttributeError, mod.f)
|
||||||
r = excinfo.getrepr(style="long", chain=mode != "explicit_suppress")
|
r = excinfo.getrepr(style="long", chain=mode != "explicit_suppress")
|
||||||
|
@ -1360,9 +1357,7 @@ raise ValueError()
|
||||||
assert tw_mock.lines[2] == " try:"
|
assert tw_mock.lines[2] == " try:"
|
||||||
assert tw_mock.lines[3] == " g()"
|
assert tw_mock.lines[3] == " g()"
|
||||||
assert tw_mock.lines[4] == " except Exception:"
|
assert tw_mock.lines[4] == " except Exception:"
|
||||||
assert tw_mock.lines[5] == "> raise AttributeError(){}".format(
|
assert tw_mock.lines[5] == f"> raise AttributeError(){raise_suffix}"
|
||||||
raise_suffix
|
|
||||||
)
|
|
||||||
assert tw_mock.lines[6] == "E AttributeError"
|
assert tw_mock.lines[6] == "E AttributeError"
|
||||||
assert tw_mock.lines[7] == ""
|
assert tw_mock.lines[7] == ""
|
||||||
line = tw_mock.get_write_msg(8)
|
line = tw_mock.get_write_msg(8)
|
||||||
|
@ -1393,7 +1388,7 @@ raise ValueError()
|
||||||
"""
|
"""
|
||||||
exc_handling_code = " from e" if reason == "cause" else ""
|
exc_handling_code = " from e" if reason == "cause" else ""
|
||||||
mod = importasmod(
|
mod = importasmod(
|
||||||
"""
|
f"""
|
||||||
def f():
|
def f():
|
||||||
try:
|
try:
|
||||||
g()
|
g()
|
||||||
|
@ -1401,9 +1396,7 @@ raise ValueError()
|
||||||
raise RuntimeError('runtime problem'){exc_handling_code}
|
raise RuntimeError('runtime problem'){exc_handling_code}
|
||||||
def g():
|
def g():
|
||||||
raise ValueError('invalid value')
|
raise ValueError('invalid value')
|
||||||
""".format(
|
"""
|
||||||
exc_handling_code=exc_handling_code
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with pytest.raises(RuntimeError) as excinfo:
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
|
|
|
@ -4,9 +4,10 @@ import sys
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.monkeypatch import MonkeyPatch
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
if sys.gettrace():
|
if sys.gettrace():
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest import deprecated
|
from _pytest import deprecated
|
||||||
from _pytest.compat import legacy_path
|
from _pytest.compat import legacy_path
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
|
import pytest
|
||||||
from pytest import PytestDeprecationWarning
|
from pytest import PytestDeprecationWarning
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
config = {"mykey": "ORIGINAL"}
|
config = {"mykey": "ORIGINAL"}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
|
|
||||||
HERE = pathlib.Path(__file__).parent
|
HERE = pathlib.Path(__file__).parent
|
||||||
TEST_CONTENT = (HERE / "template_test.py").read_bytes()
|
TEST_CONTENT = (HERE / "template_test.py").read_bytes()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
from unittest import IsolatedAsyncioTestCase
|
from unittest import IsolatedAsyncioTestCase
|
||||||
|
|
||||||
|
|
||||||
teardowns: List[None] = []
|
teardowns: List[None] = []
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ from typing import List
|
||||||
|
|
||||||
import asynctest
|
import asynctest
|
||||||
|
|
||||||
|
|
||||||
teardowns: List[None] = []
|
teardowns: List[None] = []
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import textwrap
|
|
||||||
from collections import ChainMap
|
from collections import ChainMap
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
import textwrap
|
||||||
from types import MappingProxyType
|
from types import MappingProxyType
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest._io.pprint import PrettyPrinter
|
from _pytest._io.pprint import PrettyPrinter
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import pytest
|
|
||||||
from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE
|
from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE
|
||||||
from _pytest._io.saferepr import saferepr
|
from _pytest._io.saferepr import saferepr
|
||||||
from _pytest._io.saferepr import saferepr_unlimited
|
from _pytest._io.saferepr import saferepr_unlimited
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_simple_repr():
|
def test_simple_repr():
|
||||||
|
@ -58,9 +58,7 @@ def test_exceptions() -> None:
|
||||||
obj = BrokenRepr(BrokenReprException("omg even worse"))
|
obj = BrokenRepr(BrokenReprException("omg even worse"))
|
||||||
s2 = saferepr(obj)
|
s2 = saferepr(obj)
|
||||||
assert s2 == (
|
assert s2 == (
|
||||||
"<[unpresentable exception ({!s}) raised in repr()] BrokenRepr object at 0x{:x}>".format(
|
f"<[unpresentable exception ({exp_exc!s}) raised in repr()] BrokenRepr object at 0x{id(obj):x}>"
|
||||||
exp_exc, id(obj)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,14 +96,12 @@ def test_baseexception():
|
||||||
baseexc_str = BaseException("__str__")
|
baseexc_str = BaseException("__str__")
|
||||||
obj = BrokenObj(RaisingOnStrRepr([BaseException]))
|
obj = BrokenObj(RaisingOnStrRepr([BaseException]))
|
||||||
assert saferepr(obj) == (
|
assert saferepr(obj) == (
|
||||||
"<[unpresentable exception ({!r}) "
|
f"<[unpresentable exception ({baseexc_str!r}) "
|
||||||
"raised in repr()] BrokenObj object at 0x{:x}>".format(baseexc_str, id(obj))
|
f"raised in repr()] BrokenObj object at 0x{id(obj):x}>"
|
||||||
)
|
)
|
||||||
obj = BrokenObj(RaisingOnStrRepr([RaisingOnStrRepr([BaseException])]))
|
obj = BrokenObj(RaisingOnStrRepr([RaisingOnStrRepr([BaseException])]))
|
||||||
assert saferepr(obj) == (
|
assert saferepr(obj) == (
|
||||||
"<[{!r} raised in repr()] BrokenObj object at 0x{:x}>".format(
|
f"<[{baseexc_str!r} raised in repr()] BrokenObj object at 0x{id(obj):x}>"
|
||||||
baseexc_str, id(obj)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with pytest.raises(KeyboardInterrupt):
|
with pytest.raises(KeyboardInterrupt):
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest._io import terminalwriter
|
from _pytest._io import terminalwriter
|
||||||
from _pytest.monkeypatch import MonkeyPatch
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
# These tests were initially copied from py 1.8.1.
|
# 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 wcswidth
|
||||||
from _pytest._io.wcwidth import wcwidth
|
from _pytest._io.wcwidth import wcwidth
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
import logging
|
import logging
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.logging import caplog_records_key
|
from _pytest.logging import caplog_records_key
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
sublogger = logging.getLogger(__name__ + ".baz")
|
sublogger = logging.getLogger(__name__ + ".baz")
|
||||||
|
|
|
@ -3,12 +3,12 @@ import os
|
||||||
import re
|
import re
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.capture import CaptureManager
|
from _pytest.capture import CaptureManager
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.fixtures import FixtureRequest
|
from _pytest.fixtures import FixtureRequest
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
from _pytest.terminal import TerminalReporter
|
from _pytest.terminal import TerminalReporter
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_nothing_logged(pytester: Pytester) -> None:
|
def test_nothing_logged(pytester: Pytester) -> None:
|
||||||
|
@ -176,13 +176,11 @@ def test_teardown_logging(pytester: Pytester) -> None:
|
||||||
def test_log_cli_enabled_disabled(pytester: Pytester, enabled: bool) -> None:
|
def test_log_cli_enabled_disabled(pytester: Pytester, enabled: bool) -> None:
|
||||||
msg = "critical message logged by test"
|
msg = "critical message logged by test"
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
f"""
|
||||||
import logging
|
import logging
|
||||||
def test_log_cli():
|
def test_log_cli():
|
||||||
logging.critical("{}")
|
logging.critical("{msg}")
|
||||||
""".format(
|
"""
|
||||||
msg
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if enabled:
|
if enabled:
|
||||||
pytester.makeini(
|
pytester.makeini(
|
||||||
|
@ -709,13 +707,11 @@ def test_log_file_ini(pytester: Pytester) -> None:
|
||||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||||
|
|
||||||
pytester.makeini(
|
pytester.makeini(
|
||||||
"""
|
f"""
|
||||||
[pytest]
|
[pytest]
|
||||||
log_file={}
|
log_file={log_file}
|
||||||
log_file_level=WARNING
|
log_file_level=WARNING
|
||||||
""".format(
|
"""
|
||||||
log_file
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -748,13 +744,11 @@ def test_log_file_ini_level(pytester: Pytester) -> None:
|
||||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||||
|
|
||||||
pytester.makeini(
|
pytester.makeini(
|
||||||
"""
|
f"""
|
||||||
[pytest]
|
[pytest]
|
||||||
log_file={}
|
log_file={log_file}
|
||||||
log_file_level = INFO
|
log_file_level = INFO
|
||||||
""".format(
|
"""
|
||||||
log_file
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -787,13 +781,11 @@ def test_log_file_unicode(pytester: Pytester) -> None:
|
||||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||||
|
|
||||||
pytester.makeini(
|
pytester.makeini(
|
||||||
"""
|
f"""
|
||||||
[pytest]
|
[pytest]
|
||||||
log_file={}
|
log_file={log_file}
|
||||||
log_file_level = INFO
|
log_file_level = INFO
|
||||||
""".format(
|
"""
|
||||||
log_file
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""\
|
"""\
|
||||||
|
@ -831,8 +823,8 @@ def test_live_logging_suspends_capture(
|
||||||
is installed.
|
is installed.
|
||||||
"""
|
"""
|
||||||
import contextlib
|
import contextlib
|
||||||
import logging
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
import logging
|
||||||
|
|
||||||
from _pytest.logging import _LiveLoggingStreamHandler
|
from _pytest.logging import _LiveLoggingStreamHandler
|
||||||
|
|
||||||
|
@ -923,13 +915,11 @@ def test_collection_logging_to_file(pytester: Pytester) -> None:
|
||||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||||
|
|
||||||
pytester.makeini(
|
pytester.makeini(
|
||||||
"""
|
f"""
|
||||||
[pytest]
|
[pytest]
|
||||||
log_file={}
|
log_file={log_file}
|
||||||
log_file_level = INFO
|
log_file_level = INFO
|
||||||
""".format(
|
"""
|
||||||
log_file
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
|
@ -961,14 +951,12 @@ def test_log_in_hooks(pytester: Pytester) -> None:
|
||||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||||
|
|
||||||
pytester.makeini(
|
pytester.makeini(
|
||||||
"""
|
f"""
|
||||||
[pytest]
|
[pytest]
|
||||||
log_file={}
|
log_file={log_file}
|
||||||
log_file_level = INFO
|
log_file_level = INFO
|
||||||
log_cli=true
|
log_cli=true
|
||||||
""".format(
|
"""
|
||||||
log_file
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
pytester.makeconftest(
|
pytester.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -997,14 +985,12 @@ def test_log_in_runtest_logreport(pytester: Pytester) -> None:
|
||||||
log_file = str(pytester.path.joinpath("pytest.log"))
|
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||||
|
|
||||||
pytester.makeini(
|
pytester.makeini(
|
||||||
"""
|
f"""
|
||||||
[pytest]
|
[pytest]
|
||||||
log_file={}
|
log_file={log_file}
|
||||||
log_file_level = INFO
|
log_file_level = INFO
|
||||||
log_cli=true
|
log_cli=true
|
||||||
""".format(
|
"""
|
||||||
log_file
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
pytester.makeconftest(
|
pytester.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
@ -1038,19 +1024,17 @@ def test_log_set_path(pytester: Pytester) -> None:
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
pytester.makeconftest(
|
pytester.makeconftest(
|
||||||
"""
|
f"""
|
||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
@pytest.hookimpl(wrapper=True, tryfirst=True)
|
@pytest.hookimpl(wrapper=True, tryfirst=True)
|
||||||
def pytest_runtest_setup(item):
|
def pytest_runtest_setup(item):
|
||||||
config = item.config
|
config = item.config
|
||||||
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
|
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)
|
logging_plugin.set_log_path(report_file)
|
||||||
return (yield)
|
return (yield)
|
||||||
""".format(
|
"""
|
||||||
repr(report_dir_base)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import operator
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
|
import operator
|
||||||
from operator import eq
|
from operator import eq
|
||||||
from operator import ne
|
from operator import ne
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
from _pytest.python_api import _recursive_sequence_map
|
from _pytest.python_api import _recursive_sequence_map
|
||||||
|
import pytest
|
||||||
from pytest import approx
|
from pytest import approx
|
||||||
|
|
||||||
|
|
||||||
inf, nan = float("inf"), float("nan")
|
inf, nan = float("inf"), float("nan")
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,9 +38,7 @@ def mocked_doctest_runner(monkeypatch):
|
||||||
class MyDocTestRunner(doctest.DocTestRunner):
|
class MyDocTestRunner(doctest.DocTestRunner):
|
||||||
def report_failure(self, out, test, example, got):
|
def report_failure(self, out, test, example, got):
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
"'{}' evaluates to '{}', not '{}'".format(
|
f"'{example.source.strip()}' evaluates to '{got.strip()}', not '{example.want.strip()}'"
|
||||||
example.source.strip(), got.strip(), example.want.strip()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return MyDocTestRunner()
|
return MyDocTestRunner()
|
||||||
|
|
|
@ -5,7 +5,6 @@ from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.monkeypatch import MonkeyPatch
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
|
@ -13,6 +12,7 @@ from _pytest.nodes import Collector
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
from _pytest.python import Class
|
from _pytest.python import Class
|
||||||
from _pytest.python import Function
|
from _pytest.python import Function
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
class TestModule:
|
class TestModule:
|
||||||
|
@ -53,13 +53,11 @@ class TestModule:
|
||||||
monkeypatch.syspath_prepend(str(root1))
|
monkeypatch.syspath_prepend(str(root1))
|
||||||
p.write_text(
|
p.write_text(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
"""\
|
f"""\
|
||||||
import x456
|
import x456
|
||||||
def test():
|
def test():
|
||||||
assert x456.__file__.startswith({!r})
|
assert x456.__file__.startswith({str(root2)!r})
|
||||||
""".format(
|
"""
|
||||||
str(root2)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from _pytest.compat import getfuncargnames
|
from _pytest.compat import getfuncargnames
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.fixtures import deduplicate_names
|
from _pytest.fixtures import deduplicate_names
|
||||||
|
@ -12,6 +11,7 @@ from _pytest.monkeypatch import MonkeyPatch
|
||||||
from _pytest.pytester import get_public_names
|
from _pytest.pytester import get_public_names
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
from _pytest.python import Function
|
from _pytest.python import Function
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
def test_getfuncargnames_functions():
|
def test_getfuncargnames_functions():
|
||||||
|
@ -1287,7 +1287,7 @@ class TestFixtureUsages:
|
||||||
@pytest.mark.parametrize("scope", ["function", "session"])
|
@pytest.mark.parametrize("scope", ["function", "session"])
|
||||||
def test_parameters_without_eq_semantics(self, scope, pytester: Pytester) -> None:
|
def test_parameters_without_eq_semantics(self, scope, pytester: Pytester) -> None:
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
f"""
|
||||||
class NoEq1: # fails on `a == b` statement
|
class NoEq1: # fails on `a == b` statement
|
||||||
def __eq__(self, _):
|
def __eq__(self, _):
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
@ -1309,9 +1309,7 @@ class TestFixtureUsages:
|
||||||
|
|
||||||
def test2(no_eq):
|
def test2(no_eq):
|
||||||
pass
|
pass
|
||||||
""".format(
|
"""
|
||||||
scope=scope
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
result = pytester.runpytest()
|
result = pytester.runpytest()
|
||||||
result.stdout.fnmatch_lines(["*4 passed*"])
|
result.stdout.fnmatch_lines(["*4 passed*"])
|
||||||
|
@ -2198,7 +2196,7 @@ class TestAutouseManagement:
|
||||||
pass
|
pass
|
||||||
def test_check():
|
def test_check():
|
||||||
assert values == ["new1", "new2", "fin2", "fin1"]
|
assert values == ["new1", "new2", "fin2", "fin1"]
|
||||||
"""
|
""" # noqa: UP031 (python syntax issues)
|
||||||
% locals()
|
% locals()
|
||||||
)
|
)
|
||||||
reprec = pytester.inline_run("-s")
|
reprec = pytester.inline_run("-s")
|
||||||
|
@ -3086,8 +3084,8 @@ class TestFixtureMarker:
|
||||||
pass
|
pass
|
||||||
def test_other():
|
def test_other():
|
||||||
pass
|
pass
|
||||||
"""
|
""" # noqa: UP031 (python syntax issues)
|
||||||
% {"scope": scope}
|
% {"scope": scope} # noqa: UP031 (python syntax issues)
|
||||||
)
|
)
|
||||||
reprec = pytester.inline_run("-lvs")
|
reprec = pytester.inline_run("-lvs")
|
||||||
reprec.assertoutcome(passed=3)
|
reprec.assertoutcome(passed=3)
|
||||||
|
@ -3286,7 +3284,7 @@ class TestRequestScopeAccess:
|
||||||
assert request.config
|
assert request.config
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
"""
|
""" # noqa: UP031 (python syntax issues)
|
||||||
% (scope, ok.split(), error.split())
|
% (scope, ok.split(), error.split())
|
||||||
)
|
)
|
||||||
reprec = pytester.inline_run("-l")
|
reprec = pytester.inline_run("-l")
|
||||||
|
@ -3307,7 +3305,7 @@ class TestRequestScopeAccess:
|
||||||
assert request.config
|
assert request.config
|
||||||
def test_func(arg):
|
def test_func(arg):
|
||||||
pass
|
pass
|
||||||
"""
|
""" # noqa: UP031 (python syntax issues)
|
||||||
% (scope, ok.split(), error.split())
|
% (scope, ok.split(), error.split())
|
||||||
)
|
)
|
||||||
reprec = pytester.inline_run()
|
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