Migrate from autoflake, black, isort, pyupgrade, flake8 and pydocstyle, to ruff
ruff is faster and handle everything we had prior. isort configuration done based on the indication from https://github.com/astral-sh/ruff/issues/4670, previousely based on reorder-python-import (#11896) flake8-docstrings was a wrapper around pydocstyle (now archived) that explicitly asks to use ruff in https://github.com/PyCQA/pydocstyle/pull/658. flake8-typing-import is useful mainly for project that support python 3.7 and the one useful check will be implemented in https://github.com/astral-sh/ruff/issues/2302 We need to keep blacken-doc because ruff does not handle detection of python code inside .md and .rst. The direct link to the repo is now used to avoid a redirection. Manual fixes: - Lines that became too long - % formatting that was not done automatically - type: ignore that were moved around - noqa of hard to fix issues (UP031 generally) - fmt: off and fmt: on that is not really identical between black and ruff - autofix re-order in pre-commit from faster to slower Co-authored-by: Ran Benita <ran@unusedvar.com>
This commit is contained in:
parent
046f64751b
commit
4588653b24
|
@ -1,14 +1,10 @@
|
|||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.1.1
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--safe, --quiet]
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
rev: 1.16.0
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies: [black==24.1.1]
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: "v0.1.15"
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix"]
|
||||
- id: ruff-format
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
|
@ -20,33 +16,11 @@ repos:
|
|||
- id: debug-statements
|
||||
exclude: _pytest/(debugging|hookspec).py
|
||||
language_version: python3
|
||||
- repo: https://github.com/PyCQA/autoflake
|
||||
rev: v2.2.1
|
||||
- repo: https://github.com/adamchainz/blacken-docs
|
||||
rev: 1.16.0
|
||||
hooks:
|
||||
- id: autoflake
|
||||
name: autoflake
|
||||
args: ["--in-place", "--remove-unused-variables", "--remove-all-unused-imports"]
|
||||
language: python
|
||||
files: \.py$
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
language_version: python3
|
||||
additional_dependencies:
|
||||
- flake8-typing-imports==1.12.0
|
||||
- flake8-docstrings==1.5.0
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort
|
||||
args: [--force-single-line, --profile=black]
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.15.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py38-plus]
|
||||
- id: blacken-docs
|
||||
additional_dependencies: [black==24.1.1]
|
||||
- repo: https://github.com/asottile/setup-cfg-fmt
|
||||
rev: v2.5.0
|
||||
hooks:
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
:target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main
|
||||
:alt: pre-commit.ci status
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
|
||||
.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg
|
||||
:target: https://www.codetriage.com/pytest-dev/pytest
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import sys
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import cProfile
|
||||
import pstats
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
# FastFilesCompleter 0.7383 1.0760
|
||||
import timeit
|
||||
|
||||
|
||||
imports = [
|
||||
"from argcomplete.completers import FilesCompleter as completer",
|
||||
"from _pytest._argcomplete import FastFilesCompleter as completer",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import pytest
|
||||
|
||||
|
||||
SKIP = True
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from unittest import TestCase # noqa: F401
|
||||
|
||||
|
||||
for i in range(15000):
|
||||
exec(
|
||||
f"""
|
||||
|
|
|
@ -23,6 +23,7 @@ from typing import TYPE_CHECKING
|
|||
|
||||
from _pytest import __version__ as version
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import sphinx.application
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import os.path
|
|||
|
||||
import pytest
|
||||
|
||||
|
||||
mydir = os.path.dirname(__file__)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import os.path
|
||||
import shutil
|
||||
|
||||
|
||||
failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py")
|
||||
pytest_plugins = ("pytester",)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import textwrap
|
|||
|
||||
import pytest
|
||||
|
||||
|
||||
pythonlist = ["python3.9", "python3.10", "python3.11"]
|
||||
|
||||
|
||||
|
@ -32,14 +33,12 @@ class Python:
|
|||
dumpfile = self.picklefile.with_name("dump.py")
|
||||
dumpfile.write_text(
|
||||
textwrap.dedent(
|
||||
r"""
|
||||
rf"""
|
||||
import pickle
|
||||
f = open({!r}, 'wb')
|
||||
s = pickle.dump({!r}, f, protocol=2)
|
||||
f = open({str(self.picklefile)!r}, 'wb')
|
||||
s = pickle.dump({obj!r}, f, protocol=2)
|
||||
f.close()
|
||||
""".format(
|
||||
str(self.picklefile), obj
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
subprocess.run((self.pythonpath, str(dumpfile)), check=True)
|
||||
|
@ -48,17 +47,15 @@ class Python:
|
|||
loadfile = self.picklefile.with_name("load.py")
|
||||
loadfile.write_text(
|
||||
textwrap.dedent(
|
||||
r"""
|
||||
rf"""
|
||||
import pickle
|
||||
f = open({!r}, 'rb')
|
||||
f = open({str(self.picklefile)!r}, 'rb')
|
||||
obj = pickle.load(f)
|
||||
f.close()
|
||||
res = eval({!r})
|
||||
res = eval({expression!r})
|
||||
if not res:
|
||||
raise SystemExit(1)
|
||||
""".format(
|
||||
str(self.picklefile), expression
|
||||
)
|
||||
"""
|
||||
)
|
||||
)
|
||||
print(loadfile)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import pytest
|
||||
|
||||
|
||||
xfail = pytest.mark.xfail
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ from pathlib import Path
|
|||
|
||||
import requests
|
||||
|
||||
|
||||
issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"
|
||||
|
||||
|
||||
|
|
|
@ -123,3 +123,55 @@ target-version = ['py38']
|
|||
[tool.check-wheel-contents]
|
||||
# W009: Wheel contains multiple toplevel library entries
|
||||
ignore = "W009"
|
||||
|
||||
[tool.ruff]
|
||||
src = ["src"]
|
||||
line-length = 88
|
||||
select = [
|
||||
"D", # pydocstyle
|
||||
"E", # pycodestyle
|
||||
"F", # pyflakes
|
||||
"I", # isort
|
||||
"UP", # pyupgrade
|
||||
"W", # pycodestyle
|
||||
]
|
||||
ignore = [
|
||||
# pycodestyle ignore
|
||||
# pytest can do weird low-level things, and we usually know
|
||||
# what we're doing when we use type(..) is ...
|
||||
"E721", # Do not compare types, use `isinstance()`
|
||||
# pydocstyle ignore
|
||||
"D100", # Missing docstring in public module
|
||||
"D101", # Missing docstring in public class
|
||||
"D102", # Missing docstring in public method
|
||||
"D103", # Missing docstring in public function
|
||||
"D104", # Missing docstring in public package
|
||||
"D105", # Missing docstring in magic method
|
||||
"D106", # Missing docstring in public nested class
|
||||
"D107", # Missing docstring in `__init__`
|
||||
"D209", # [*] Multi-line docstring closing quotes should be on a separate line
|
||||
"D205", # 1 blank line required between summary line and description
|
||||
"D400", # First line should end with a period
|
||||
"D401", # First line of docstring should be in imperative mood
|
||||
"D402", # First line should not be the function's signature
|
||||
"D404", # First word of the docstring should not be "This"
|
||||
"D415", # First line should end with a period, question mark, or exclamation point
|
||||
]
|
||||
|
||||
[tool.ruff.format]
|
||||
docstring-code-format = true
|
||||
|
||||
[tool.ruff.lint.pycodestyle]
|
||||
# In order to be able to format for 88 char in ruff format
|
||||
max-line-length = 120
|
||||
|
||||
[tool.ruff.lint.pydocstyle]
|
||||
convention = "pep257"
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
force-single-line = true
|
||||
combine-as-imports = true
|
||||
force-sort-within-sections = true
|
||||
order-by-type = false
|
||||
known-local-folder = ["pytest", "_pytest"]
|
||||
lines-after-imports = 2
|
||||
|
|
|
@ -8,9 +8,9 @@ our CHANGELOG) into Markdown (which is required by GitHub Releases).
|
|||
|
||||
Requires Python3.6+.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Sequence
|
||||
|
||||
import pypandoc
|
||||
|
|
|
@ -14,8 +14,8 @@ After that, it will create a release using the `release` tox environment, and pu
|
|||
`pytest bot <pytestbot@gmail.com>` commit author.
|
||||
"""
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
import re
|
||||
from subprocess import check_call
|
||||
from subprocess import check_output
|
||||
from subprocess import run
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# mypy: disallow-untyped-defs
|
||||
import sys
|
||||
from subprocess import call
|
||||
import sys
|
||||
|
||||
|
||||
def main() -> int:
|
||||
|
|
|
@ -11,13 +11,14 @@ from typing import TypedDict
|
|||
|
||||
import packaging.version
|
||||
import platformdirs
|
||||
import tabulate
|
||||
import wcwidth
|
||||
from requests_cache import CachedResponse
|
||||
from requests_cache import CachedSession
|
||||
from requests_cache import OriginalResponse
|
||||
from requests_cache import SQLiteCache
|
||||
import tabulate
|
||||
from tqdm import tqdm
|
||||
import wcwidth
|
||||
|
||||
|
||||
FILE_HEAD = r"""
|
||||
.. Note this file is autogenerated by scripts/update-plugin-list.py - usually weekly via github action
|
||||
|
@ -85,7 +86,6 @@ def project_response_with_refresh(
|
|||
|
||||
force refresh in case of last serial mismatch
|
||||
"""
|
||||
|
||||
response = session.get(f"https://pypi.org/pypi/{name}/json")
|
||||
if int(response.headers.get("X-PyPI-Last-Serial", -1)) != last_serial:
|
||||
response = session.get(f"https://pypi.org/pypi/{name}/json", refresh=True)
|
||||
|
@ -184,7 +184,6 @@ def iter_plugins() -> Iterator[PluginInfo]:
|
|||
|
||||
def plugin_definitions(plugins: Iterable[PluginInfo]) -> Iterator[str]:
|
||||
"""Return RST for the plugin list that fits better on a vertical page."""
|
||||
|
||||
for plugin in plugins:
|
||||
yield dedent(
|
||||
f"""
|
||||
|
|
|
@ -63,9 +63,9 @@ If things do not work right away:
|
|||
"""
|
||||
|
||||
import argparse
|
||||
from glob import glob
|
||||
import os
|
||||
import sys
|
||||
from glob import glob
|
||||
from typing import Any
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
|
|
@ -10,6 +10,7 @@ from .code import TracebackEntry
|
|||
from .source import getrawcode
|
||||
from .source import Source
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Code",
|
||||
"ExceptionInfo",
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
import ast
|
||||
import dataclasses
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
from inspect import CO_VARARGS
|
||||
from inspect import CO_VARKEYWORDS
|
||||
from io import StringIO
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
from traceback import format_exception_only
|
||||
from types import CodeType
|
||||
from types import FrameType
|
||||
|
@ -51,6 +51,7 @@ from _pytest.deprecated import check_ispytest
|
|||
from _pytest.pathlib import absolutepath
|
||||
from _pytest.pathlib import bestrelpath
|
||||
|
||||
|
||||
if sys.version_info[:2] < (3, 11):
|
||||
from exceptiongroup import BaseExceptionGroup
|
||||
|
||||
|
@ -278,9 +279,9 @@ class TracebackEntry:
|
|||
|
||||
Mostly for internal use.
|
||||
"""
|
||||
tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = (
|
||||
False
|
||||
)
|
||||
tbh: Union[
|
||||
bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]
|
||||
] = False
|
||||
for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals):
|
||||
# in normal cases, f_locals and f_globals are dictionaries
|
||||
# however via `exec(...)` / `eval(...)` they can be other types
|
||||
|
@ -377,10 +378,12 @@ class Traceback(List[TracebackEntry]):
|
|||
return self
|
||||
|
||||
@overload
|
||||
def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ...
|
||||
def __getitem__(self, key: "SupportsIndex") -> TracebackEntry:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __getitem__(self, key: slice) -> "Traceback": ...
|
||||
def __getitem__(self, key: slice) -> "Traceback":
|
||||
...
|
||||
|
||||
def __getitem__(
|
||||
self, key: Union["SupportsIndex", slice]
|
||||
|
@ -485,9 +488,10 @@ class ExceptionInfo(Generic[E]):
|
|||
|
||||
.. versionadded:: 7.4
|
||||
"""
|
||||
assert (
|
||||
exception.__traceback__
|
||||
), "Exceptions passed to ExcInfo.from_exception(...) must have a non-None __traceback__."
|
||||
assert exception.__traceback__, (
|
||||
"Exceptions passed to ExcInfo.from_exception(...)"
|
||||
" must have a non-None __traceback__."
|
||||
)
|
||||
exc_info = (type(exception), exception, exception.__traceback__)
|
||||
return cls.from_exc_info(exc_info, exprinfo)
|
||||
|
||||
|
@ -586,9 +590,7 @@ class ExceptionInfo(Generic[E]):
|
|||
def __repr__(self) -> str:
|
||||
if self._excinfo is None:
|
||||
return "<ExceptionInfo for raises contextmanager>"
|
||||
return "<{} {} tblen={}>".format(
|
||||
self.__class__.__name__, saferepr(self._excinfo[1]), len(self.traceback)
|
||||
)
|
||||
return f"<{self.__class__.__name__} {saferepr(self._excinfo[1])} tblen={len(self.traceback)}>"
|
||||
|
||||
def exconly(self, tryshort: bool = False) -> str:
|
||||
"""Return the exception as a string.
|
||||
|
@ -1016,13 +1018,8 @@ class FormattedExcinfo:
|
|||
extraline: Optional[str] = (
|
||||
"!!! Recursion error detected, but an error occurred locating the origin of recursion.\n"
|
||||
" The following exception happened when comparing locals in the stack frame:\n"
|
||||
" {exc_type}: {exc_msg}\n"
|
||||
" Displaying first and last {max_frames} stack frames out of {total}."
|
||||
).format(
|
||||
exc_type=type(e).__name__,
|
||||
exc_msg=str(e),
|
||||
max_frames=max_frames,
|
||||
total=len(traceback),
|
||||
f" {type(e).__name__}: {str(e)}\n"
|
||||
f" Displaying first and last {max_frames} stack frames out of {len(traceback)}."
|
||||
)
|
||||
# Type ignored because adding two instances of a List subtype
|
||||
# currently incorrectly has type List instead of the subtype.
|
||||
|
@ -1054,13 +1051,13 @@ class FormattedExcinfo:
|
|||
# full support for exception groups added to ExceptionInfo.
|
||||
# See https://github.com/pytest-dev/pytest/issues/9159
|
||||
if isinstance(e, BaseExceptionGroup):
|
||||
reprtraceback: Union[ReprTracebackNative, ReprTraceback] = (
|
||||
ReprTracebackNative(
|
||||
traceback.format_exception(
|
||||
type(excinfo_.value),
|
||||
excinfo_.value,
|
||||
excinfo_.traceback[0]._rawentry,
|
||||
)
|
||||
reprtraceback: Union[
|
||||
ReprTracebackNative, ReprTraceback
|
||||
] = ReprTracebackNative(
|
||||
traceback.format_exception(
|
||||
type(excinfo_.value),
|
||||
excinfo_.value,
|
||||
excinfo_.traceback[0]._rawentry,
|
||||
)
|
||||
)
|
||||
else:
|
||||
|
@ -1229,7 +1226,6 @@ class ReprEntry(TerminalRepr):
|
|||
the "E" prefix) using syntax highlighting, taking care to not highlighting the ">"
|
||||
character, as doing so might break line continuations.
|
||||
"""
|
||||
|
||||
if not self.lines:
|
||||
return
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import ast
|
||||
from bisect import bisect_right
|
||||
import inspect
|
||||
import textwrap
|
||||
import tokenize
|
||||
import types
|
||||
import warnings
|
||||
from bisect import bisect_right
|
||||
from typing import Iterable
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
|
@ -13,6 +12,7 @@ from typing import Optional
|
|||
from typing import overload
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
|
||||
class Source:
|
||||
|
@ -47,10 +47,12 @@ class Source:
|
|||
__hash__ = None # type: ignore
|
||||
|
||||
@overload
|
||||
def __getitem__(self, key: int) -> str: ...
|
||||
def __getitem__(self, key: int) -> str:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __getitem__(self, key: slice) -> "Source": ...
|
||||
def __getitem__(self, key: slice) -> "Source":
|
||||
...
|
||||
|
||||
def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]:
|
||||
if isinstance(key, int):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from .terminalwriter import get_terminal_width
|
||||
from .terminalwriter import TerminalWriter
|
||||
|
||||
|
||||
__all__ = [
|
||||
"TerminalWriter",
|
||||
"get_terminal_width",
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
# useful, thank small children who sleep at night.
|
||||
import collections as _collections
|
||||
import dataclasses as _dataclasses
|
||||
from io import StringIO as _StringIO
|
||||
import re
|
||||
import types as _types
|
||||
from io import StringIO as _StringIO
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
|
|
|
@ -19,8 +19,8 @@ def _format_repr_exception(exc: BaseException, obj: object) -> str:
|
|||
raise
|
||||
except BaseException as exc:
|
||||
exc_info = f"unpresentable exception ({_try_repr_or_str(exc)})"
|
||||
return "<[{} raised in repr()] {} object at 0x{:x}>".format(
|
||||
exc_info, type(obj).__name__, id(obj)
|
||||
return (
|
||||
f"<[{exc_info} raised in repr()] {type(obj).__name__} object at 0x{id(obj):x}>"
|
||||
)
|
||||
|
||||
|
||||
|
@ -108,7 +108,6 @@ def saferepr(
|
|||
This function is a wrapper around the Repr/reprlib functionality of the
|
||||
stdlib.
|
||||
"""
|
||||
|
||||
return SafeRepr(maxsize, use_ascii).repr(obj)
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ from typing import TextIO
|
|||
|
||||
from .wcwidth import wcswidth
|
||||
|
||||
|
||||
# This code was initially copied from py 1.8.1, file _io/terminalwriter.py.
|
||||
|
||||
|
||||
|
@ -183,9 +184,7 @@ class TerminalWriter:
|
|||
"""
|
||||
if indents and len(indents) != len(lines):
|
||||
raise ValueError(
|
||||
"indents size ({}) should have same size as lines ({})".format(
|
||||
len(indents), len(lines)
|
||||
)
|
||||
f"indents size ({len(indents)}) should have same size as lines ({len(lines)})"
|
||||
)
|
||||
if not indents:
|
||||
indents = [""] * len(lines)
|
||||
|
@ -210,8 +209,8 @@ class TerminalWriter:
|
|||
from pygments.lexers.python import PythonLexer as Lexer
|
||||
elif lexer == "diff":
|
||||
from pygments.lexers.diff import DiffLexer as Lexer
|
||||
import pygments.util
|
||||
from pygments import highlight
|
||||
import pygments.util
|
||||
except ImportError:
|
||||
return source
|
||||
else:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import unicodedata
|
||||
from functools import lru_cache
|
||||
import unicodedata
|
||||
|
||||
|
||||
@lru_cache(100)
|
||||
|
|
|
@ -9,6 +9,7 @@ from typing import Callable
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
|
|
|
@ -3,15 +3,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import atexit
|
||||
from contextlib import contextmanager
|
||||
import fnmatch
|
||||
import importlib.util
|
||||
import io
|
||||
import os
|
||||
import posixpath
|
||||
import sys
|
||||
import uuid
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
from os.path import abspath
|
||||
from os.path import dirname
|
||||
from os.path import exists
|
||||
|
@ -20,18 +16,23 @@ from os.path import isdir
|
|||
from os.path import isfile
|
||||
from os.path import islink
|
||||
from os.path import normpath
|
||||
import posixpath
|
||||
from stat import S_ISDIR
|
||||
from stat import S_ISLNK
|
||||
from stat import S_ISREG
|
||||
import sys
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import cast
|
||||
from typing import Literal
|
||||
from typing import overload
|
||||
from typing import TYPE_CHECKING
|
||||
import uuid
|
||||
import warnings
|
||||
|
||||
from . import error
|
||||
|
||||
|
||||
# Moved from local.py.
|
||||
iswin32 = sys.platform == "win32" or (getattr(os, "_name", False) == "nt")
|
||||
|
||||
|
@ -204,10 +205,12 @@ class Stat:
|
|||
if TYPE_CHECKING:
|
||||
|
||||
@property
|
||||
def size(self) -> int: ...
|
||||
def size(self) -> int:
|
||||
...
|
||||
|
||||
@property
|
||||
def mtime(self) -> float: ...
|
||||
def mtime(self) -> float:
|
||||
...
|
||||
|
||||
def __getattr__(self, name: str) -> Any:
|
||||
return getattr(self._osstatresult, "st_" + name)
|
||||
|
@ -674,7 +677,7 @@ class LocalPath:
|
|||
else:
|
||||
kw.setdefault("dirname", dirname)
|
||||
kw.setdefault("sep", self.sep)
|
||||
obj.strpath = normpath("%(dirname)s%(sep)s%(basename)s" % kw)
|
||||
obj.strpath = normpath("{dirname}{sep}{basename}".format(**kw))
|
||||
return obj
|
||||
|
||||
def _getbyspec(self, spec: str) -> list[str]:
|
||||
|
@ -759,7 +762,10 @@ class LocalPath:
|
|||
# expected "Callable[[str, Any, Any], TextIOWrapper]" [arg-type]
|
||||
# Which seems incorrect, given io.open supports the given argument types.
|
||||
return error.checked_call(
|
||||
io.open, self.strpath, mode, encoding=encoding # type:ignore[arg-type]
|
||||
io.open,
|
||||
self.strpath,
|
||||
mode,
|
||||
encoding=encoding, # type:ignore[arg-type]
|
||||
)
|
||||
return error.checked_call(open, self.strpath, mode)
|
||||
|
||||
|
@ -778,11 +784,11 @@ class LocalPath:
|
|||
|
||||
valid checkers::
|
||||
|
||||
file=1 # is a file
|
||||
file=0 # is not a file (may not even exist)
|
||||
dir=1 # is a dir
|
||||
link=1 # is a link
|
||||
exists=1 # exists
|
||||
file = 1 # is a file
|
||||
file = 0 # is not a file (may not even exist)
|
||||
dir = 1 # is a dir
|
||||
link = 1 # is a link
|
||||
exists = 1 # exists
|
||||
|
||||
You can specify multiple checker definitions, for example::
|
||||
|
||||
|
@ -960,10 +966,12 @@ class LocalPath:
|
|||
return p
|
||||
|
||||
@overload
|
||||
def stat(self, raising: Literal[True] = ...) -> Stat: ...
|
||||
def stat(self, raising: Literal[True] = ...) -> Stat:
|
||||
...
|
||||
|
||||
@overload
|
||||
def stat(self, raising: Literal[False]) -> Stat | None: ...
|
||||
def stat(self, raising: Literal[False]) -> Stat | None:
|
||||
...
|
||||
|
||||
def stat(self, raising: bool = True) -> Stat | None:
|
||||
"""Return an os.stat() tuple."""
|
||||
|
@ -1275,7 +1283,8 @@ class LocalPath:
|
|||
# error: Argument 1 has incompatible type overloaded function; expected "Callable[[str], str]" [arg-type]
|
||||
# Which seems incorrect, given tempfile.mkdtemp supports the given argument types.
|
||||
path = error.checked_call(
|
||||
tempfile.mkdtemp, dir=str(rootdir) # type:ignore[arg-type]
|
||||
tempfile.mkdtemp,
|
||||
dir=str(rootdir), # type:ignore[arg-type]
|
||||
)
|
||||
return cls(path)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ from _pytest.config import hookimpl
|
|||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.nodes import Item
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest.main import Session
|
||||
|
||||
|
@ -129,7 +130,6 @@ def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]:
|
|||
reporting via the pytest_assertrepr_compare hook. This sets up this custom
|
||||
comparison for the test.
|
||||
"""
|
||||
|
||||
ihook = item.ihook
|
||||
|
||||
def callbinrepr(op, left: object, right: object) -> Optional[str]:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Rewrite assertion AST to produce nice error messages."""
|
||||
|
||||
import ast
|
||||
from collections import defaultdict
|
||||
import errno
|
||||
import functools
|
||||
import importlib.abc
|
||||
|
@ -10,13 +11,12 @@ import io
|
|||
import itertools
|
||||
import marshal
|
||||
import os
|
||||
from pathlib import Path
|
||||
from pathlib import PurePath
|
||||
import struct
|
||||
import sys
|
||||
import tokenize
|
||||
import types
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from pathlib import PurePath
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
from typing import IO
|
||||
|
@ -40,6 +40,7 @@ from _pytest.pathlib import absolutepath
|
|||
from _pytest.pathlib import fnmatch_ex
|
||||
from _pytest.stash import StashKey
|
||||
|
||||
|
||||
# fmt: off
|
||||
from _pytest.assertion.util import format_explanation as _format_explanation # noqa:F401, isort:skip
|
||||
# fmt:on
|
||||
|
@ -671,9 +672,9 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
self.enable_assertion_pass_hook = False
|
||||
self.source = source
|
||||
self.scope: tuple[ast.AST, ...] = ()
|
||||
self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = (
|
||||
defaultdict(dict)
|
||||
)
|
||||
self.variables_overwrite: defaultdict[
|
||||
tuple[ast.AST, ...], Dict[str, str]
|
||||
] = defaultdict(dict)
|
||||
|
||||
def run(self, mod: ast.Module) -> None:
|
||||
"""Find all assert statements in *mod* and rewrite them."""
|
||||
|
@ -1019,9 +1020,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
]
|
||||
):
|
||||
pytest_temp = self.variable()
|
||||
self.variables_overwrite[self.scope][
|
||||
v.left.target.id
|
||||
] = v.left # type:ignore[assignment]
|
||||
self.variables_overwrite[self.scope][v.left.target.id] = v.left # type:ignore[assignment]
|
||||
v.left.target.id = pytest_temp
|
||||
self.push_format_context()
|
||||
res, expl = self.visit(v)
|
||||
|
@ -1065,9 +1064,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite.get(
|
||||
self.scope, {}
|
||||
):
|
||||
arg = self.variables_overwrite[self.scope][
|
||||
arg.id
|
||||
] # type:ignore[assignment]
|
||||
arg = self.variables_overwrite[self.scope][arg.id] # type:ignore[assignment]
|
||||
res, expl = self.visit(arg)
|
||||
arg_expls.append(expl)
|
||||
new_args.append(res)
|
||||
|
@ -1075,9 +1072,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
if isinstance(
|
||||
keyword.value, ast.Name
|
||||
) and keyword.value.id in self.variables_overwrite.get(self.scope, {}):
|
||||
keyword.value = self.variables_overwrite[self.scope][
|
||||
keyword.value.id
|
||||
] # type:ignore[assignment]
|
||||
keyword.value = self.variables_overwrite[self.scope][keyword.value.id] # type:ignore[assignment]
|
||||
res, expl = self.visit(keyword.value)
|
||||
new_kwargs.append(ast.keyword(keyword.arg, res))
|
||||
if keyword.arg:
|
||||
|
@ -1114,13 +1109,9 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
if isinstance(
|
||||
comp.left, ast.Name
|
||||
) and comp.left.id in self.variables_overwrite.get(self.scope, {}):
|
||||
comp.left = self.variables_overwrite[self.scope][
|
||||
comp.left.id
|
||||
] # type:ignore[assignment]
|
||||
comp.left = self.variables_overwrite[self.scope][comp.left.id] # type:ignore[assignment]
|
||||
if isinstance(comp.left, ast.NamedExpr):
|
||||
self.variables_overwrite[self.scope][
|
||||
comp.left.target.id
|
||||
] = comp.left # type:ignore[assignment]
|
||||
self.variables_overwrite[self.scope][comp.left.target.id] = comp.left # type:ignore[assignment]
|
||||
left_res, left_expl = self.visit(comp.left)
|
||||
if isinstance(comp.left, (ast.Compare, ast.BoolOp)):
|
||||
left_expl = f"({left_expl})"
|
||||
|
@ -1138,9 +1129,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
|||
and next_operand.target.id == left_res.id
|
||||
):
|
||||
next_operand.target.id = self.variable()
|
||||
self.variables_overwrite[self.scope][
|
||||
left_res.id
|
||||
] = next_operand # type:ignore[assignment]
|
||||
self.variables_overwrite[self.scope][left_res.id] = next_operand # type:ignore[assignment]
|
||||
next_res, next_expl = self.visit(next_operand)
|
||||
if isinstance(next_operand, (ast.Compare, ast.BoolOp)):
|
||||
next_expl = f"({next_expl})"
|
||||
|
|
|
@ -11,6 +11,7 @@ from _pytest.assertion import util
|
|||
from _pytest.config import Config
|
||||
from _pytest.nodes import Item
|
||||
|
||||
|
||||
DEFAULT_MAX_LINES = 8
|
||||
DEFAULT_MAX_CHARS = 8 * 80
|
||||
USAGE_MSG = "use '-vv' to show"
|
||||
|
|
|
@ -15,13 +15,14 @@ from typing import Protocol
|
|||
from typing import Sequence
|
||||
from unicodedata import normalize
|
||||
|
||||
import _pytest._code
|
||||
from _pytest import outcomes
|
||||
import _pytest._code
|
||||
from _pytest._io.pprint import PrettyPrinter
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest._io.saferepr import saferepr_unlimited
|
||||
from _pytest.config import Config
|
||||
|
||||
|
||||
# The _reprcompare attribute on the util module is used by the new assertion
|
||||
# interpretation code and assertion rewriter to detect this plugin was
|
||||
# loaded and in turn call the hooks defined here as part of the
|
||||
|
@ -302,8 +303,8 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]:
|
|||
if i > 42:
|
||||
i -= 10 # Provide some context
|
||||
explanation += [
|
||||
"Skipping {} identical trailing "
|
||||
"characters in diff, use -v to show".format(i)
|
||||
f"Skipping {i} identical trailing "
|
||||
"characters in diff, use -v to show"
|
||||
]
|
||||
left = left[:-i]
|
||||
right = right[:-i]
|
||||
|
|
|
@ -32,6 +32,7 @@ from _pytest.nodes import Directory
|
|||
from _pytest.nodes import File
|
||||
from _pytest.reports import TestReport
|
||||
|
||||
|
||||
README_CONTENT = """\
|
||||
# pytest cache directory #
|
||||
|
||||
|
@ -368,15 +369,13 @@ class LFPlugin:
|
|||
|
||||
noun = "failure" if self._previously_failed_count == 1 else "failures"
|
||||
suffix = " first" if self.config.getoption("failedfirst") else ""
|
||||
self._report_status = "rerun previous {count} {noun}{suffix}".format(
|
||||
count=self._previously_failed_count, suffix=suffix, noun=noun
|
||||
self._report_status = (
|
||||
f"rerun previous {self._previously_failed_count} {noun}{suffix}"
|
||||
)
|
||||
|
||||
if self._skipped_files > 0:
|
||||
files_noun = "file" if self._skipped_files == 1 else "files"
|
||||
self._report_status += " (skipped {files} {files_noun})".format(
|
||||
files=self._skipped_files, files_noun=files_noun
|
||||
)
|
||||
self._report_status += f" (skipped {self._skipped_files} {files_noun})"
|
||||
else:
|
||||
self._report_status = "no previously failed tests, "
|
||||
if self.config.getoption("last_failed_no_failures") == "none":
|
||||
|
|
|
@ -4,9 +4,9 @@ import abc
|
|||
import collections
|
||||
import contextlib
|
||||
import io
|
||||
from io import UnsupportedOperation
|
||||
import os
|
||||
import sys
|
||||
from io import UnsupportedOperation
|
||||
from tempfile import TemporaryFile
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
|
@ -39,6 +39,7 @@ from _pytest.nodes import File
|
|||
from _pytest.nodes import Item
|
||||
from _pytest.reports import CollectReport
|
||||
|
||||
|
||||
_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
|
||||
|
||||
|
||||
|
@ -790,9 +791,7 @@ class CaptureManager:
|
|||
current_fixture = self._capture_fixture.request.fixturename
|
||||
requested_fixture = capture_fixture.request.fixturename
|
||||
capture_fixture.request.raiseerror(
|
||||
"cannot use {} and {} at the same time".format(
|
||||
requested_fixture, current_fixture
|
||||
)
|
||||
f"cannot use {requested_fixture} and {current_fixture} at the same time"
|
||||
)
|
||||
self._capture_fixture = capture_fixture
|
||||
|
||||
|
@ -988,7 +987,6 @@ def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
|
|||
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_output(capsys):
|
||||
|
@ -1016,7 +1014,6 @@ def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None,
|
|||
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_output(capsysbinary):
|
||||
|
@ -1044,7 +1041,6 @@ def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
|
|||
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_system_echo(capfd):
|
||||
|
@ -1072,7 +1068,6 @@ def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, N
|
|||
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_system_echo(capfdbinary):
|
||||
|
|
|
@ -6,17 +6,18 @@ import dataclasses
|
|||
import enum
|
||||
import functools
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
from inspect import Parameter
|
||||
from inspect import signature
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Final
|
||||
from typing import NoReturn
|
||||
from typing import TypeVar
|
||||
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_S = TypeVar("_S")
|
||||
|
||||
|
@ -243,9 +244,7 @@ def get_real_func(obj):
|
|||
from _pytest._io.saferepr import saferepr
|
||||
|
||||
raise ValueError(
|
||||
("could not find real function of {start}\nstopped at {current}").format(
|
||||
start=saferepr(start_obj), current=saferepr(obj)
|
||||
)
|
||||
f"could not find real function of {saferepr(start_obj)}\nstopped at {saferepr(obj)}"
|
||||
)
|
||||
if isinstance(obj, functools.partial):
|
||||
obj = obj.func
|
||||
|
|
|
@ -5,18 +5,17 @@ import collections.abc
|
|||
import copy
|
||||
import dataclasses
|
||||
import enum
|
||||
from functools import lru_cache
|
||||
import glob
|
||||
import importlib.metadata
|
||||
import inspect
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shlex
|
||||
import sys
|
||||
import types
|
||||
import warnings
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
import types
|
||||
from types import FunctionType
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
|
@ -37,6 +36,7 @@ from typing import Tuple
|
|||
from typing import Type
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
from pluggy import HookimplMarker
|
||||
from pluggy import HookimplOpts
|
||||
|
@ -44,15 +44,15 @@ from pluggy import HookspecMarker
|
|||
from pluggy import HookspecOpts
|
||||
from pluggy import PluginManager
|
||||
|
||||
import _pytest._code
|
||||
import _pytest.deprecated
|
||||
import _pytest.hookspec
|
||||
from .exceptions import PrintHelp as PrintHelp
|
||||
from .exceptions import UsageError as UsageError
|
||||
from .findpaths import determine_setup
|
||||
import _pytest._code
|
||||
from _pytest._code import ExceptionInfo
|
||||
from _pytest._code import filter_traceback
|
||||
from _pytest._io import TerminalWriter
|
||||
import _pytest.deprecated
|
||||
import _pytest.hookspec
|
||||
from _pytest.outcomes import fail
|
||||
from _pytest.outcomes import Skipped
|
||||
from _pytest.pathlib import absolutepath
|
||||
|
@ -65,6 +65,7 @@ from _pytest.stash import Stash
|
|||
from _pytest.warning_types import PytestConfigWarning
|
||||
from _pytest.warning_types import warn_explicit_for
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .argparsing import Argument
|
||||
from .argparsing import Parser
|
||||
|
@ -813,7 +814,7 @@ class PytestPluginManager(PluginManager):
|
|||
|
||||
|
||||
def _get_plugin_specs_as_list(
|
||||
specs: Union[None, types.ModuleType, str, Sequence[str]]
|
||||
specs: Union[None, types.ModuleType, str, Sequence[str]],
|
||||
) -> List[str]:
|
||||
"""Parse a plugins specification into a list of plugin names."""
|
||||
# None means empty.
|
||||
|
@ -1374,12 +1375,7 @@ class Config:
|
|||
|
||||
if Version(minver) > Version(pytest.__version__):
|
||||
raise pytest.UsageError(
|
||||
"%s: 'minversion' requires pytest-%s, actual pytest-%s'"
|
||||
% (
|
||||
self.inipath,
|
||||
minver,
|
||||
pytest.__version__,
|
||||
)
|
||||
f"{self.inipath}: 'minversion' requires pytest-{minver}, actual pytest-{pytest.__version__}'"
|
||||
)
|
||||
|
||||
def _validate_config_options(self) -> None:
|
||||
|
@ -1614,9 +1610,7 @@ class Config:
|
|||
key, user_ini_value = ini_config.split("=", 1)
|
||||
except ValueError as e:
|
||||
raise UsageError(
|
||||
"-o/--override-ini expects option=value style (got: {!r}).".format(
|
||||
ini_config
|
||||
)
|
||||
f"-o/--override-ini expects option=value style (got: {ini_config!r})."
|
||||
) from e
|
||||
else:
|
||||
if key == name:
|
||||
|
@ -1674,7 +1668,6 @@ class Config:
|
|||
can be used to explicitly use the global verbosity level.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import argparse
|
||||
from gettext import gettext
|
||||
import os
|
||||
import sys
|
||||
from gettext import gettext
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import cast
|
||||
|
@ -21,6 +21,7 @@ import _pytest._io
|
|||
from _pytest.config.exceptions import UsageError
|
||||
from _pytest.deprecated import check_ispytest
|
||||
|
||||
|
||||
FILE_OR_DIR = "file_or_dir"
|
||||
|
||||
|
||||
|
@ -216,7 +217,7 @@ class Parser:
|
|||
|
||||
|
||||
def get_ini_default_for_type(
|
||||
type: Optional[Literal["string", "paths", "pathlist", "args", "linelist", "bool"]]
|
||||
type: Optional[Literal["string", "paths", "pathlist", "args", "linelist", "bool"]],
|
||||
) -> Any:
|
||||
"""
|
||||
Used by addini to get the default value for a given ini-option type, when
|
||||
|
@ -448,7 +449,7 @@ class MyOptionParser(argparse.ArgumentParser):
|
|||
) -> Optional[Tuple[Optional[argparse.Action], str, Optional[str]]]:
|
||||
if not arg_string:
|
||||
return None
|
||||
if not arg_string[0] in self.prefix_chars:
|
||||
if arg_string[0] not in self.prefix_chars:
|
||||
return None
|
||||
if arg_string in self._option_string_actions:
|
||||
action = self._option_string_actions[arg_string]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import Dict
|
||||
from typing import Iterable
|
||||
from typing import List
|
||||
|
@ -37,7 +37,6 @@ def load_config_dict_from_file(
|
|||
|
||||
Return None if the file does not contain valid pytest configuration.
|
||||
"""
|
||||
|
||||
# Configuration from ini files are obtained from the [pytest] section, if present.
|
||||
if filepath.suffix == ".ini":
|
||||
iniconfig = _parse_ini_config(filepath)
|
||||
|
@ -213,9 +212,7 @@ def determine_setup(
|
|||
rootdir = absolutepath(os.path.expandvars(rootdir_cmd_arg))
|
||||
if not rootdir.is_dir():
|
||||
raise UsageError(
|
||||
"Directory '{}' not found. Check your '--rootdir' option.".format(
|
||||
rootdir
|
||||
)
|
||||
f"Directory '{rootdir}' not found. Check your '--rootdir' option."
|
||||
)
|
||||
assert rootdir is not None
|
||||
return rootdir, inipath, inicfg or {}
|
||||
|
|
|
@ -4,7 +4,6 @@ import argparse
|
|||
import functools
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Generator
|
||||
|
@ -14,6 +13,7 @@ from typing import Tuple
|
|||
from typing import Type
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
import unittest
|
||||
|
||||
from _pytest import outcomes
|
||||
from _pytest._code import ExceptionInfo
|
||||
|
@ -26,6 +26,7 @@ from _pytest.config.exceptions import UsageError
|
|||
from _pytest.nodes import Node
|
||||
from _pytest.reports import BaseReport
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest.capture import CaptureManager
|
||||
from _pytest.runner import CallInfo
|
||||
|
@ -264,8 +265,7 @@ class pytestPDB:
|
|||
elif capturing:
|
||||
tw.sep(
|
||||
">",
|
||||
"PDB %s (IO-capturing turned off for %s)"
|
||||
% (method, capturing),
|
||||
f"PDB {method} (IO-capturing turned off for {capturing})",
|
||||
)
|
||||
else:
|
||||
tw.sep(">", f"PDB {method}")
|
||||
|
|
|
@ -15,6 +15,7 @@ from _pytest.warning_types import PytestDeprecationWarning
|
|||
from _pytest.warning_types import PytestRemovedIn9Warning
|
||||
from _pytest.warning_types import UnformattedWarning
|
||||
|
||||
|
||||
# set of plugins which have been integrated into the core; we use this list to ignore
|
||||
# them during registration to avoid conflicts
|
||||
DEPRECATED_EXTERNAL_PLUGINS = {
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Discover and run doctests in modules and test files."""
|
||||
import bdb
|
||||
from contextlib import contextmanager
|
||||
import functools
|
||||
import inspect
|
||||
import os
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import sys
|
||||
import traceback
|
||||
import types
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
|
@ -24,6 +23,7 @@ from typing import Tuple
|
|||
from typing import Type
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
from _pytest import outcomes
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
|
@ -45,6 +45,7 @@ from _pytest.python import Module
|
|||
from _pytest.python_api import approx
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import doctest
|
||||
|
||||
|
@ -486,9 +487,9 @@ def _patch_unwrap_mock_aware() -> Generator[None, None, None]:
|
|||
return real_unwrap(func, stop=lambda obj: _is_mocked(obj) or _stop(func))
|
||||
except Exception as e:
|
||||
warnings.warn(
|
||||
"Got %r when unwrapping %r. This is usually caused "
|
||||
f"Got {e!r} when unwrapping {func!r}. This is usually caused "
|
||||
"by a violation of Python's object protocol; see e.g. "
|
||||
"https://github.com/pytest-dev/pytest/issues/5080" % (e, func),
|
||||
"https://github.com/pytest-dev/pytest/issues/5080",
|
||||
PytestWarning,
|
||||
)
|
||||
raise
|
||||
|
|
|
@ -2,11 +2,12 @@ import os
|
|||
import sys
|
||||
from typing import Generator
|
||||
|
||||
import pytest
|
||||
from _pytest.config import Config
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.nodes import Item
|
||||
from _pytest.stash import StashKey
|
||||
import pytest
|
||||
|
||||
|
||||
fault_handler_original_stderr_fd_key = StashKey[int]()
|
||||
fault_handler_stderr_fd_key = StashKey[int]()
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import abc
|
||||
from collections import defaultdict
|
||||
from collections import deque
|
||||
from contextlib import suppress
|
||||
import dataclasses
|
||||
import functools
|
||||
import inspect
|
||||
import os
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from collections import deque
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
from typing import AbstractSet
|
||||
from typing import Any
|
||||
|
@ -31,6 +30,7 @@ from typing import Tuple
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
import _pytest
|
||||
from _pytest import nodes
|
||||
|
@ -67,6 +67,7 @@ from _pytest.scope import _ScopeName
|
|||
from _pytest.scope import HIGH_SCOPES
|
||||
from _pytest.scope import Scope
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Deque
|
||||
|
||||
|
@ -601,13 +602,9 @@ class FixtureRequest(abc.ABC):
|
|||
fixtures_not_supported = getattr(funcitem, "nofuncargs", False)
|
||||
if has_params and fixtures_not_supported:
|
||||
msg = (
|
||||
"{name} does not support fixtures, maybe unittest.TestCase subclass?\n"
|
||||
"Node id: {nodeid}\n"
|
||||
"Function type: {typename}"
|
||||
).format(
|
||||
name=funcitem.name,
|
||||
nodeid=funcitem.nodeid,
|
||||
typename=type(funcitem).__name__,
|
||||
f"{funcitem.name} does not support fixtures, maybe unittest.TestCase subclass?\n"
|
||||
f"Node id: {funcitem.nodeid}\n"
|
||||
f"Function type: {type(funcitem).__name__}"
|
||||
)
|
||||
fail(msg, pytrace=False)
|
||||
if has_params:
|
||||
|
@ -740,9 +737,7 @@ class SubRequest(FixtureRequest):
|
|||
if node is None and scope is Scope.Class:
|
||||
# Fallback to function item itself.
|
||||
node = self._pyfuncitem
|
||||
assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format(
|
||||
scope, self._pyfuncitem
|
||||
)
|
||||
assert node, f'Could not obtain a node for scope "{scope}" for function {self._pyfuncitem!r}'
|
||||
return node
|
||||
|
||||
def _check_scope(
|
||||
|
@ -845,8 +840,8 @@ class FixtureLookupError(LookupError):
|
|||
if faclist:
|
||||
available.add(name)
|
||||
if self.argname in available:
|
||||
msg = " recursive dependency involving fixture '{}' detected".format(
|
||||
self.argname
|
||||
msg = (
|
||||
f" recursive dependency involving fixture '{self.argname}' detected"
|
||||
)
|
||||
else:
|
||||
msg = f"fixture '{self.argname}' not found"
|
||||
|
@ -940,15 +935,13 @@ def _eval_scope_callable(
|
|||
result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg]
|
||||
except Exception as e:
|
||||
raise TypeError(
|
||||
"Error evaluating {} while defining fixture '{}'.\n"
|
||||
"Expected a function with the signature (*, fixture_name, config)".format(
|
||||
scope_callable, fixture_name
|
||||
)
|
||||
f"Error evaluating {scope_callable} while defining fixture '{fixture_name}'.\n"
|
||||
"Expected a function with the signature (*, fixture_name, config)"
|
||||
) from e
|
||||
if not isinstance(result, str):
|
||||
fail(
|
||||
"Expected {} to return a 'str' while defining fixture '{}', but it returned:\n"
|
||||
"{!r}".format(scope_callable, fixture_name, result),
|
||||
f"Expected {scope_callable} to return a 'str' while defining fixture '{fixture_name}', but it returned:\n"
|
||||
f"{result!r}",
|
||||
pytrace=False,
|
||||
)
|
||||
return result
|
||||
|
@ -1090,9 +1083,7 @@ class FixtureDef(Generic[FixtureValue]):
|
|||
return request.param_index if not hasattr(request, "param") else request.param
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<FixtureDef argname={!r} scope={!r} baseid={!r}>".format(
|
||||
self.argname, self.scope, self.baseid
|
||||
)
|
||||
return f"<FixtureDef argname={self.argname!r} scope={self.scope!r} baseid={self.baseid!r}>"
|
||||
|
||||
|
||||
def resolve_fixture_function(
|
||||
|
@ -1113,7 +1104,8 @@ def resolve_fixture_function(
|
|||
# Handle the case where fixture is defined not in a test class, but some other class
|
||||
# (for example a plugin class with a fixture), see #2270.
|
||||
if hasattr(fixturefunc, "__self__") and not isinstance(
|
||||
request.instance, fixturefunc.__self__.__class__ # type: ignore[union-attr]
|
||||
request.instance,
|
||||
fixturefunc.__self__.__class__, # type: ignore[union-attr]
|
||||
):
|
||||
return fixturefunc
|
||||
fixturefunc = getimfunc(fixturedef.func)
|
||||
|
@ -1208,9 +1200,7 @@ class FixtureFunctionMarker:
|
|||
if name == "request":
|
||||
location = getlocation(function)
|
||||
fail(
|
||||
"'request' is a reserved word for fixtures, use another name:\n {}".format(
|
||||
location
|
||||
),
|
||||
f"'request' is a reserved word for fixtures, use another name:\n {location}",
|
||||
pytrace=False,
|
||||
)
|
||||
|
||||
|
@ -1230,7 +1220,8 @@ def fixture(
|
|||
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
|
||||
] = ...,
|
||||
name: Optional[str] = ...,
|
||||
) -> FixtureFunction: ...
|
||||
) -> FixtureFunction:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
|
@ -1244,7 +1235,8 @@ def fixture( # noqa: F811
|
|||
Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
|
||||
] = ...,
|
||||
name: Optional[str] = None,
|
||||
) -> FixtureFunctionMarker: ...
|
||||
) -> FixtureFunctionMarker:
|
||||
...
|
||||
|
||||
|
||||
def fixture( # noqa: F811
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Version info, help messages, tracing configuration."""
|
||||
from argparse import Action
|
||||
import os
|
||||
import sys
|
||||
from argparse import Action
|
||||
from typing import Generator
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
import pytest
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.config import PrintHelp
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.terminal import TerminalReporter
|
||||
import pytest
|
||||
|
||||
|
||||
class HelpAction(Action):
|
||||
|
@ -109,9 +109,8 @@ def pytest_cmdline_parse() -> Generator[None, Config, Config]:
|
|||
path = config.option.debug
|
||||
debugfile = open(path, "w", encoding="utf-8")
|
||||
debugfile.write(
|
||||
"versions pytest-%s, "
|
||||
"python-%s\ninvocation_dir=%s\ncwd=%s\nargs=%s\n\n"
|
||||
% (
|
||||
"versions pytest-{}, "
|
||||
"python-{}\ninvocation_dir={}\ncwd={}\nargs={}\n\n".format(
|
||||
pytest.__version__,
|
||||
".".join(map(str, sys.version_info)),
|
||||
config.invocation_params.dir,
|
||||
|
@ -137,9 +136,7 @@ def pytest_cmdline_parse() -> Generator[None, Config, Config]:
|
|||
def showversion(config: Config) -> None:
|
||||
if config.option.version > 1:
|
||||
sys.stdout.write(
|
||||
"This is pytest version {}, imported from {}\n".format(
|
||||
pytest.__version__, pytest.__file__
|
||||
)
|
||||
f"This is pytest version {pytest.__version__}, imported from {pytest.__file__}\n"
|
||||
)
|
||||
plugininfo = getpluginversioninfo(config)
|
||||
if plugininfo:
|
||||
|
|
|
@ -14,10 +14,11 @@ from typing import Union
|
|||
|
||||
from pluggy import HookspecMarker
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pdb
|
||||
import warnings
|
||||
from typing import Literal
|
||||
import warnings
|
||||
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
from _pytest._code.code import ExceptionRepr
|
||||
|
|
|
@ -7,12 +7,11 @@ Based on initial code from Ross Lawley.
|
|||
Output conforms to
|
||||
https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
|
||||
"""
|
||||
from datetime import datetime
|
||||
import functools
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
|
@ -20,8 +19,8 @@ from typing import Match
|
|||
from typing import Optional
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
import pytest
|
||||
from _pytest import nodes
|
||||
from _pytest import timing
|
||||
from _pytest._code.code import ExceptionRepr
|
||||
|
@ -33,6 +32,8 @@ from _pytest.fixtures import FixtureRequest
|
|||
from _pytest.reports import TestReport
|
||||
from _pytest.stash import StashKey
|
||||
from _pytest.terminal import TerminalReporter
|
||||
import pytest
|
||||
|
||||
|
||||
xml_key = StashKey["LogXML"]()
|
||||
|
||||
|
@ -273,9 +274,7 @@ def _warn_incompatibility_with_xunit2(
|
|||
if xml is not None and xml.family not in ("xunit1", "legacy"):
|
||||
request.node.warn(
|
||||
PytestWarning(
|
||||
"{fixture_name} is incompatible with junit_family '{family}' (use 'legacy' or 'xunit1')".format(
|
||||
fixture_name=fixture_name, family=xml.family
|
||||
)
|
||||
f"{fixture_name} is incompatible with junit_family '{xml.family}' (use 'legacy' or 'xunit1')"
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -367,7 +366,6 @@ def record_testsuite_property(request: FixtureRequest) -> Callable[[str, object]
|
|||
`pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See
|
||||
:issue:`7767` for details.
|
||||
"""
|
||||
|
||||
__tracebackhide__ = True
|
||||
|
||||
def record_func(name: str, value: object) -> None:
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
"""Add backward compatibility support for the legacy py path type."""
|
||||
import dataclasses
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shlex
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
from typing import final
|
||||
from typing import List
|
||||
|
@ -34,6 +34,7 @@ from _pytest.pytester import RunResult
|
|||
from _pytest.terminal import TerminalReporter
|
||||
from _pytest.tmpdir import TempPathFactory
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pexpect
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Access and control log capturing."""
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from contextlib import contextmanager
|
||||
from contextlib import nullcontext
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from datetime import timezone
|
||||
import io
|
||||
from io import StringIO
|
||||
import logging
|
||||
from logging import LogRecord
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
from types import TracebackType
|
||||
from typing import AbstractSet
|
||||
from typing import Dict
|
||||
|
@ -44,6 +44,7 @@ from _pytest.main import Session
|
|||
from _pytest.stash import StashKey
|
||||
from _pytest.terminal import TerminalReporter
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
logging_StreamHandler = logging.StreamHandler[StringIO]
|
||||
else:
|
||||
|
@ -116,7 +117,6 @@ class ColoredLevelFormatter(DatetimeFormatter):
|
|||
.. warning::
|
||||
This is an experimental API.
|
||||
"""
|
||||
|
||||
assert self._fmt is not None
|
||||
levelname_fmt_match = self.LEVELNAME_FMT_REGEX.search(self._fmt)
|
||||
if not levelname_fmt_match:
|
||||
|
@ -183,7 +183,6 @@ class PercentStyleMultiline(logging.PercentStyle):
|
|||
0 (auto-indent turned off) or
|
||||
>0 (explicitly set indentation position).
|
||||
"""
|
||||
|
||||
if auto_indent_option is None:
|
||||
return 0
|
||||
elif isinstance(auto_indent_option, bool):
|
||||
|
@ -625,9 +624,9 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i
|
|||
except ValueError as e:
|
||||
# Python logging does not recognise this as a logging level
|
||||
raise UsageError(
|
||||
"'{}' is not recognized as a logging level name for "
|
||||
"'{}'. Please consider passing the "
|
||||
"logging level num instead.".format(log_level, setting_name)
|
||||
f"'{log_level}' is not recognized as a logging level name for "
|
||||
f"'{setting_name}'. Please consider passing the "
|
||||
"logging level num instead."
|
||||
) from e
|
||||
|
||||
|
||||
|
|
|
@ -6,9 +6,8 @@ import fnmatch
|
|||
import functools
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from typing import AbstractSet
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
|
@ -23,11 +22,12 @@ from typing import overload
|
|||
from typing import Sequence
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
import pluggy
|
||||
|
||||
import _pytest._code
|
||||
from _pytest import nodes
|
||||
import _pytest._code
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import directory_arg
|
||||
from _pytest.config import ExitCode
|
||||
|
@ -722,12 +722,14 @@ class Session(nodes.Collector):
|
|||
@overload
|
||||
def perform_collect(
|
||||
self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ...
|
||||
) -> Sequence[nodes.Item]: ...
|
||||
) -> Sequence[nodes.Item]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def perform_collect( # noqa: F811
|
||||
self, args: Optional[Sequence[str]] = ..., genitems: bool = ...
|
||||
) -> Sequence[Union[nodes.Item, nodes.Collector]]: ...
|
||||
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
|
||||
...
|
||||
|
||||
def perform_collect( # noqa: F811
|
||||
self, args: Optional[Sequence[str]] = None, genitems: bool = True
|
||||
|
|
|
@ -24,6 +24,7 @@ from _pytest.config import UsageError
|
|||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.stash import StashKey
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest.nodes import Item
|
||||
|
||||
|
@ -268,8 +269,8 @@ def pytest_configure(config: Config) -> None:
|
|||
|
||||
if empty_parameterset not in ("skip", "xfail", "fail_at_collect", None, ""):
|
||||
raise UsageError(
|
||||
"{!s} must be one of skip, xfail or fail_at_collect"
|
||||
" but it is {!r}".format(EMPTY_PARAMETERSET_OPTION, empty_parameterset)
|
||||
f"{EMPTY_PARAMETERSET_OPTION!s} must be one of skip, xfail or fail_at_collect"
|
||||
f" but it is {empty_parameterset!r}"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ from typing import NoReturn
|
|||
from typing import Optional
|
||||
from typing import Sequence
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Expression",
|
||||
"ParseError",
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import collections.abc
|
||||
import dataclasses
|
||||
import inspect
|
||||
import warnings
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Collection
|
||||
|
@ -22,6 +21,7 @@ from typing import Type
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
from .._code import getfslineno
|
||||
from ..compat import ascii_escaped
|
||||
|
@ -33,6 +33,7 @@ from _pytest.deprecated import MARKED_FIXTURE
|
|||
from _pytest.outcomes import fail
|
||||
from _pytest.warning_types import PytestUnknownMarkWarning
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..nodes import Node
|
||||
|
||||
|
@ -112,7 +113,6 @@ class ParameterSet(NamedTuple):
|
|||
Enforce tuple wrapping so single argument tuple values
|
||||
don't get decomposed and break tests.
|
||||
"""
|
||||
|
||||
if isinstance(parameterset, cls):
|
||||
return parameterset
|
||||
if force_tuple:
|
||||
|
@ -272,8 +272,8 @@ class MarkDecorator:
|
|||
|
||||
``MarkDecorators`` are created with ``pytest.mark``::
|
||||
|
||||
mark1 = pytest.mark.NAME # Simple MarkDecorator
|
||||
mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator
|
||||
mark1 = pytest.mark.NAME # Simple MarkDecorator
|
||||
mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator
|
||||
|
||||
and can then be applied as decorators to test functions::
|
||||
|
||||
|
@ -394,7 +394,7 @@ def get_unpacked_marks(
|
|||
|
||||
|
||||
def normalize_mark_list(
|
||||
mark_list: Iterable[Union[Mark, MarkDecorator]]
|
||||
mark_list: Iterable[Union[Mark, MarkDecorator]],
|
||||
) -> Iterable[Mark]:
|
||||
"""
|
||||
Normalize an iterable of Mark or MarkDecorator objects into a list of marks
|
||||
|
@ -434,10 +434,12 @@ if TYPE_CHECKING:
|
|||
|
||||
class _SkipMarkDecorator(MarkDecorator):
|
||||
@overload # type: ignore[override,misc,no-overload-impl]
|
||||
def __call__(self, arg: Markable) -> Markable: ...
|
||||
def __call__(self, arg: Markable) -> Markable:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __call__(self, reason: str = ...) -> "MarkDecorator": ...
|
||||
def __call__(self, reason: str = ...) -> "MarkDecorator":
|
||||
...
|
||||
|
||||
class _SkipifMarkDecorator(MarkDecorator):
|
||||
def __call__( # type: ignore[override]
|
||||
|
@ -445,11 +447,13 @@ if TYPE_CHECKING:
|
|||
condition: Union[str, bool] = ...,
|
||||
*conditions: Union[str, bool],
|
||||
reason: str = ...,
|
||||
) -> MarkDecorator: ...
|
||||
) -> MarkDecorator:
|
||||
...
|
||||
|
||||
class _XfailMarkDecorator(MarkDecorator):
|
||||
@overload # type: ignore[override,misc,no-overload-impl]
|
||||
def __call__(self, arg: Markable) -> Markable: ...
|
||||
def __call__(self, arg: Markable) -> Markable:
|
||||
...
|
||||
|
||||
@overload
|
||||
def __call__(
|
||||
|
@ -462,7 +466,8 @@ if TYPE_CHECKING:
|
|||
None, Type[BaseException], Tuple[Type[BaseException], ...]
|
||||
] = ...,
|
||||
strict: bool = ...,
|
||||
) -> MarkDecorator: ...
|
||||
) -> MarkDecorator:
|
||||
...
|
||||
|
||||
class _ParametrizeMarkDecorator(MarkDecorator):
|
||||
def __call__( # type: ignore[override]
|
||||
|
@ -478,7 +483,8 @@ if TYPE_CHECKING:
|
|||
]
|
||||
] = ...,
|
||||
scope: Optional[_ScopeName] = ...,
|
||||
) -> MarkDecorator: ...
|
||||
) -> MarkDecorator:
|
||||
...
|
||||
|
||||
class _UsefixturesMarkDecorator(MarkDecorator):
|
||||
def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override]
|
||||
|
@ -498,9 +504,10 @@ class MarkGenerator:
|
|||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.slowtest
|
||||
def test_function():
|
||||
pass
|
||||
pass
|
||||
|
||||
applies a 'slowtest' :class:`Mark` on ``test_function``.
|
||||
"""
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Monkeypatching and mocking functionality."""
|
||||
from contextlib import contextmanager
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
from typing import Any
|
||||
from typing import final
|
||||
from typing import Generator
|
||||
|
@ -16,10 +15,12 @@ from typing import overload
|
|||
from typing import Tuple
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
from _pytest.fixtures import fixture
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
||||
|
||||
RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$")
|
||||
|
||||
|
||||
|
@ -90,9 +91,7 @@ def annotated_getattr(obj: object, name: str, ann: str) -> object:
|
|||
obj = getattr(obj, name)
|
||||
except AttributeError as e:
|
||||
raise AttributeError(
|
||||
"{!r} object at {} has no attribute {!r}".format(
|
||||
type(obj).__name__, ann, name
|
||||
)
|
||||
f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}"
|
||||
) from e
|
||||
return obj
|
||||
|
||||
|
@ -142,7 +141,6 @@ class MonkeyPatch:
|
|||
which undoes any patching done inside the ``with`` block upon exit.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import functools
|
||||
|
@ -169,7 +167,8 @@ class MonkeyPatch:
|
|||
name: object,
|
||||
value: Notset = ...,
|
||||
raising: bool = ...,
|
||||
) -> None: ...
|
||||
) -> None:
|
||||
...
|
||||
|
||||
@overload
|
||||
def setattr(
|
||||
|
@ -178,7 +177,8 @@ class MonkeyPatch:
|
|||
name: str,
|
||||
value: object,
|
||||
raising: bool = ...,
|
||||
) -> None: ...
|
||||
) -> None:
|
||||
...
|
||||
|
||||
def setattr(
|
||||
self,
|
||||
|
@ -320,10 +320,8 @@ class MonkeyPatch:
|
|||
if not isinstance(value, str):
|
||||
warnings.warn( # type: ignore[unreachable]
|
||||
PytestWarning(
|
||||
"Value of environment variable {name} type should be str, but got "
|
||||
"{value!r} (type: {type}); converted to str implicitly".format(
|
||||
name=name, value=value, type=type(value).__name__
|
||||
)
|
||||
f"Value of environment variable {name} type should be str, but got "
|
||||
f"{value!r} (type: {type(value).__name__}); converted to str implicitly"
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
@ -343,7 +341,6 @@ class MonkeyPatch:
|
|||
|
||||
def syspath_prepend(self, path) -> None:
|
||||
"""Prepend ``path`` to ``sys.path`` list of import locations."""
|
||||
|
||||
if self._savesyspath is None:
|
||||
self._savesyspath = sys.path[:]
|
||||
sys.path.insert(0, str(path))
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import abc
|
||||
import os
|
||||
import warnings
|
||||
from functools import cached_property
|
||||
from inspect import signature
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
|
@ -20,6 +19,7 @@ from typing import Type
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
import pluggy
|
||||
|
||||
|
@ -39,6 +39,7 @@ from _pytest.pathlib import commonpath
|
|||
from _pytest.stash import Stash
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# Imported here due to circular import.
|
||||
from _pytest._code.code import _TracebackStyle
|
||||
|
@ -229,9 +230,7 @@ class Node(abc.ABC, metaclass=NodeMeta):
|
|||
# enforce type checks here to avoid getting a generic type error later otherwise.
|
||||
if not isinstance(warning, Warning):
|
||||
raise ValueError(
|
||||
"warning must be an instance of Warning or subclass, got {!r}".format(
|
||||
warning
|
||||
)
|
||||
f"warning must be an instance of Warning or subclass, got {warning!r}"
|
||||
)
|
||||
path, lineno = get_fslocation_from_item(self)
|
||||
assert lineno is not None
|
||||
|
@ -326,10 +325,12 @@ class Node(abc.ABC, metaclass=NodeMeta):
|
|||
yield node, mark
|
||||
|
||||
@overload
|
||||
def get_closest_marker(self, name: str) -> Optional[Mark]: ...
|
||||
def get_closest_marker(self, name: str) -> Optional[Mark]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def get_closest_marker(self, name: str, default: Mark) -> Mark: ...
|
||||
def get_closest_marker(self, name: str, default: Mark) -> Mark:
|
||||
...
|
||||
|
||||
def get_closest_marker(
|
||||
self, name: str, default: Optional[Mark] = None
|
||||
|
|
|
@ -239,8 +239,7 @@ def importorskip(
|
|||
|
||||
if verattr is None or Version(verattr) < Version(minversion):
|
||||
raise Skipped(
|
||||
"module %r has __version__ %r, required is: %r"
|
||||
% (modname, verattr, minversion),
|
||||
f"module {modname!r} has __version__ {verattr!r}, required is: {minversion!r}",
|
||||
allow_module_level=True,
|
||||
)
|
||||
return mod
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Submit failure or test session information to a pastebin service."""
|
||||
import tempfile
|
||||
from io import StringIO
|
||||
import tempfile
|
||||
from typing import IO
|
||||
from typing import Union
|
||||
|
||||
import pytest
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import create_terminal_writer
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.stash import StashKey
|
||||
from _pytest.terminal import TerminalReporter
|
||||
import pytest
|
||||
|
||||
|
||||
pastebinfile_key = StashKey[IO[bytes]]()
|
||||
|
||||
|
|
|
@ -1,21 +1,16 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import atexit
|
||||
import contextlib
|
||||
import fnmatch
|
||||
import importlib.util
|
||||
import itertools
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import types
|
||||
import uuid
|
||||
import warnings
|
||||
from enum import Enum
|
||||
from errno import EBADF
|
||||
from errno import ELOOP
|
||||
from errno import ENOENT
|
||||
from errno import ENOTDIR
|
||||
import fnmatch
|
||||
from functools import partial
|
||||
import importlib.util
|
||||
import itertools
|
||||
import os
|
||||
from os.path import expanduser
|
||||
from os.path import expandvars
|
||||
from os.path import isabs
|
||||
|
@ -23,6 +18,9 @@ from os.path import sep
|
|||
from pathlib import Path
|
||||
from pathlib import PurePath
|
||||
from posixpath import sep as posix_sep
|
||||
import shutil
|
||||
import sys
|
||||
import types
|
||||
from types import ModuleType
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
|
@ -35,11 +33,14 @@ from typing import Tuple
|
|||
from typing import Type
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
import uuid
|
||||
import warnings
|
||||
|
||||
from _pytest.compat import assert_never
|
||||
from _pytest.outcomes import skip
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
||||
|
||||
LOCK_TIMEOUT = 60 * 60 * 24 * 3
|
||||
|
||||
|
||||
|
@ -102,9 +103,7 @@ def on_rm_rf_error(
|
|||
if func not in (os.open,):
|
||||
warnings.warn(
|
||||
PytestWarning(
|
||||
"(rm_rf) unknown function {} when removing {}:\n{}: {}".format(
|
||||
func, path, type(exc), exc
|
||||
)
|
||||
f"(rm_rf) unknown function {func} when removing {path}:\n{type(exc)}: {exc}"
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
@ -243,7 +242,7 @@ def make_numbered_dir(root: Path, prefix: str, mode: int = 0o700) -> Path:
|
|||
else:
|
||||
raise OSError(
|
||||
"could not create numbered dir with prefix "
|
||||
"{prefix} in {root} after 10 tries".format(prefix=prefix, root=root)
|
||||
f"{prefix} in {root} after 10 tries"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -5,19 +5,19 @@ PYTEST_DONT_REWRITE
|
|||
"""
|
||||
import collections.abc
|
||||
import contextlib
|
||||
from fnmatch import fnmatch
|
||||
import gc
|
||||
import importlib
|
||||
from io import StringIO
|
||||
import locale
|
||||
import os
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
from fnmatch import fnmatch
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
|
@ -70,6 +70,7 @@ from _pytest.reports import TestReport
|
|||
from _pytest.tmpdir import TempPathFactory
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pexpect
|
||||
|
||||
|
@ -187,7 +188,7 @@ class LsofFdLeakChecker:
|
|||
"*** After:",
|
||||
*(str(f) for f in lines2),
|
||||
"***** %s FD leakage detected" % len(leaked_files),
|
||||
"*** function %s:%s: %s " % item.location,
|
||||
"*** function {}:{}: {} ".format(*item.location),
|
||||
"See issue #2366",
|
||||
]
|
||||
item.warn(PytestWarning("\n".join(error)))
|
||||
|
@ -244,7 +245,8 @@ class RecordedHookCall:
|
|||
|
||||
if TYPE_CHECKING:
|
||||
# The class has undetermined attributes, this tells mypy about it.
|
||||
def __getattr__(self, key: str): ...
|
||||
def __getattr__(self, key: str):
|
||||
...
|
||||
|
||||
|
||||
@final
|
||||
|
@ -325,13 +327,15 @@ class HookRecorder:
|
|||
def getreports(
|
||||
self,
|
||||
names: "Literal['pytest_collectreport']",
|
||||
) -> Sequence[CollectReport]: ...
|
||||
) -> Sequence[CollectReport]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def getreports(
|
||||
self,
|
||||
names: "Literal['pytest_runtest_logreport']",
|
||||
) -> Sequence[TestReport]: ...
|
||||
) -> Sequence[TestReport]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def getreports(
|
||||
|
@ -340,7 +344,8 @@ class HookRecorder:
|
|||
"pytest_collectreport",
|
||||
"pytest_runtest_logreport",
|
||||
),
|
||||
) -> Sequence[Union[CollectReport, TestReport]]: ...
|
||||
) -> Sequence[Union[CollectReport, TestReport]]:
|
||||
...
|
||||
|
||||
def getreports(
|
||||
self,
|
||||
|
@ -372,14 +377,12 @@ class HookRecorder:
|
|||
values.append(rep)
|
||||
if not values:
|
||||
raise ValueError(
|
||||
"could not find test report matching %r: "
|
||||
"no test reports at all!" % (inamepart,)
|
||||
f"could not find test report matching {inamepart!r}: "
|
||||
"no test reports at all!"
|
||||
)
|
||||
if len(values) > 1:
|
||||
raise ValueError(
|
||||
"found 2 or more testreports matching {!r}: {}".format(
|
||||
inamepart, values
|
||||
)
|
||||
f"found 2 or more testreports matching {inamepart!r}: {values}"
|
||||
)
|
||||
return values[0]
|
||||
|
||||
|
@ -387,13 +390,15 @@ class HookRecorder:
|
|||
def getfailures(
|
||||
self,
|
||||
names: "Literal['pytest_collectreport']",
|
||||
) -> Sequence[CollectReport]: ...
|
||||
) -> Sequence[CollectReport]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def getfailures(
|
||||
self,
|
||||
names: "Literal['pytest_runtest_logreport']",
|
||||
) -> Sequence[TestReport]: ...
|
||||
) -> Sequence[TestReport]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def getfailures(
|
||||
|
@ -402,7 +407,8 @@ class HookRecorder:
|
|||
"pytest_collectreport",
|
||||
"pytest_runtest_logreport",
|
||||
),
|
||||
) -> Sequence[Union[CollectReport, TestReport]]: ...
|
||||
) -> Sequence[Union[CollectReport, TestReport]]:
|
||||
...
|
||||
|
||||
def getfailures(
|
||||
self,
|
||||
|
@ -801,7 +807,6 @@ class Pytester:
|
|||
The first created file.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pytester.makefile(".txt", "line1", "line2")
|
||||
|
@ -855,7 +860,6 @@ class Pytester:
|
|||
existing files.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_something(pytester):
|
||||
|
@ -875,7 +879,6 @@ class Pytester:
|
|||
existing files.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_something(pytester):
|
||||
|
@ -1265,9 +1268,7 @@ class Pytester:
|
|||
for item in items:
|
||||
if item.name == funcname:
|
||||
return item
|
||||
assert 0, "{!r} item not found in module:\n{}\nitems: {}".format(
|
||||
funcname, source, items
|
||||
)
|
||||
assert 0, f"{funcname!r} item not found in module:\n{source}\nitems: {items}"
|
||||
|
||||
def getitems(self, source: Union[str, "os.PathLike[str]"]) -> List[Item]:
|
||||
"""Return all test items collected from the module.
|
||||
|
@ -1426,10 +1427,7 @@ class Pytester:
|
|||
def handle_timeout() -> None:
|
||||
__tracebackhide__ = True
|
||||
|
||||
timeout_message = (
|
||||
"{seconds} second timeout expired running:"
|
||||
" {command}".format(seconds=timeout, command=cmdargs)
|
||||
)
|
||||
timeout_message = f"{timeout} second timeout expired running: {cmdargs}"
|
||||
|
||||
popen.kill()
|
||||
popen.wait()
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Python test discovery, setup and run of test functions."""
|
||||
import abc
|
||||
from collections import Counter
|
||||
from collections import defaultdict
|
||||
import dataclasses
|
||||
import enum
|
||||
import fnmatch
|
||||
from functools import partial
|
||||
import inspect
|
||||
import itertools
|
||||
import os
|
||||
import types
|
||||
import warnings
|
||||
from collections import Counter
|
||||
from collections import defaultdict
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
import types
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Dict
|
||||
|
@ -29,6 +28,7 @@ from typing import Sequence
|
|||
from typing import Set
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
import _pytest
|
||||
from _pytest import fixtures
|
||||
|
@ -81,6 +81,7 @@ from _pytest.warning_types import PytestCollectionWarning
|
|||
from _pytest.warning_types import PytestReturnNotNoneWarning
|
||||
from _pytest.warning_types import PytestUnhandledCoroutineWarning
|
||||
|
||||
|
||||
_PYTEST_DIR = Path(_pytest.__file__).parent
|
||||
|
||||
|
||||
|
@ -263,8 +264,8 @@ def pytest_pycollect_makeitem(
|
|||
elif getattr(obj, "__test__", True):
|
||||
if is_generator(obj):
|
||||
res: Function = Function.from_parent(collector, name=name)
|
||||
reason = "yield tests were removed in pytest 4.0 - {name} will be ignored".format(
|
||||
name=name
|
||||
reason = (
|
||||
f"yield tests were removed in pytest 4.0 - {name} will be ignored"
|
||||
)
|
||||
res.add_marker(MARK_GEN.xfail(run=False, reason=reason))
|
||||
res.warn(PytestCollectionWarning(reason))
|
||||
|
@ -524,12 +525,12 @@ def importtestmodule(
|
|||
except ImportPathMismatchError as e:
|
||||
raise nodes.Collector.CollectError(
|
||||
"import file mismatch:\n"
|
||||
"imported module %r has this __file__ attribute:\n"
|
||||
" %s\n"
|
||||
"imported module {!r} has this __file__ attribute:\n"
|
||||
" {}\n"
|
||||
"which is not the same as the test file we want to collect:\n"
|
||||
" %s\n"
|
||||
" {}\n"
|
||||
"HINT: remove __pycache__ / .pyc files and/or use a "
|
||||
"unique basename for your test file modules" % e.args
|
||||
"unique basename for your test file modules".format(*e.args)
|
||||
) from e
|
||||
except ImportError as e:
|
||||
exc_info = ExceptionInfo.from_current()
|
||||
|
@ -542,10 +543,10 @@ def importtestmodule(
|
|||
)
|
||||
formatted_tb = str(exc_repr)
|
||||
raise nodes.Collector.CollectError(
|
||||
"ImportError while importing test module '{path}'.\n"
|
||||
f"ImportError while importing test module '{path}'.\n"
|
||||
"Hint: make sure your test modules/packages have valid Python names.\n"
|
||||
"Traceback:\n"
|
||||
"{traceback}".format(path=path, traceback=formatted_tb)
|
||||
f"{formatted_tb}"
|
||||
) from e
|
||||
except skip.Exception as e:
|
||||
if e.allow_module_level:
|
||||
|
@ -765,9 +766,8 @@ class Class(PyCollector):
|
|||
assert self.parent is not None
|
||||
self.warn(
|
||||
PytestCollectionWarning(
|
||||
"cannot collect test class %r because it has a "
|
||||
"__init__ constructor (from: %s)"
|
||||
% (self.obj.__name__, self.parent.nodeid)
|
||||
f"cannot collect test class {self.obj.__name__!r} because it has a "
|
||||
f"__init__ constructor (from: {self.parent.nodeid})"
|
||||
)
|
||||
)
|
||||
return []
|
||||
|
@ -775,9 +775,8 @@ class Class(PyCollector):
|
|||
assert self.parent is not None
|
||||
self.warn(
|
||||
PytestCollectionWarning(
|
||||
"cannot collect test class %r because it has a "
|
||||
"__new__ constructor (from: %s)"
|
||||
% (self.obj.__name__, self.parent.nodeid)
|
||||
f"cannot collect test class {self.obj.__name__!r} because it has a "
|
||||
f"__new__ constructor (from: {self.parent.nodeid})"
|
||||
)
|
||||
)
|
||||
return []
|
||||
|
@ -1432,17 +1431,14 @@ class Metafunc:
|
|||
for arg in indirect:
|
||||
if arg not in argnames:
|
||||
fail(
|
||||
"In {}: indirect fixture '{}' doesn't exist".format(
|
||||
self.function.__name__, arg
|
||||
),
|
||||
f"In {self.function.__name__}: indirect fixture '{arg}' doesn't exist",
|
||||
pytrace=False,
|
||||
)
|
||||
arg_directness[arg] = "indirect"
|
||||
else:
|
||||
fail(
|
||||
"In {func}: expected Sequence or boolean for indirect, got {type}".format(
|
||||
type=type(indirect).__name__, func=self.function.__name__
|
||||
),
|
||||
f"In {self.function.__name__}: expected Sequence or boolean"
|
||||
f" for indirect, got {type(indirect).__name__}",
|
||||
pytrace=False,
|
||||
)
|
||||
return arg_directness
|
||||
|
@ -1464,9 +1460,7 @@ class Metafunc:
|
|||
if arg not in self.fixturenames:
|
||||
if arg in default_arg_names:
|
||||
fail(
|
||||
"In {}: function already takes an argument '{}' with a default value".format(
|
||||
func_name, arg
|
||||
),
|
||||
f"In {func_name}: function already takes an argument '{arg}' with a default value",
|
||||
pytrace=False,
|
||||
)
|
||||
else:
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import math
|
||||
import pprint
|
||||
from collections.abc import Collection
|
||||
from collections.abc import Sized
|
||||
from decimal import Decimal
|
||||
import math
|
||||
from numbers import Complex
|
||||
import pprint
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
|
@ -27,6 +27,7 @@ import _pytest._code
|
|||
from _pytest.compat import STRING_TYPES
|
||||
from _pytest.outcomes import fail
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from numpy import ndarray
|
||||
|
||||
|
@ -238,9 +239,7 @@ class ApproxMapping(ApproxBase):
|
|||
with numeric values (the keys can be anything)."""
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "approx({!r})".format(
|
||||
{k: self._approx_scalar(v) for k, v in self.expected.items()}
|
||||
)
|
||||
return f"approx({({k: self._approx_scalar(v) for k, v in self.expected.items()})!r})"
|
||||
|
||||
def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]:
|
||||
import math
|
||||
|
@ -315,9 +314,7 @@ class ApproxSequenceLike(ApproxBase):
|
|||
seq_type = type(self.expected)
|
||||
if seq_type not in (tuple, list):
|
||||
seq_type = list
|
||||
return "approx({!r})".format(
|
||||
seq_type(self._approx_scalar(x) for x in self.expected)
|
||||
)
|
||||
return f"approx({seq_type(self._approx_scalar(x) for x in self.expected)!r})"
|
||||
|
||||
def _repr_compare(self, other_side: Sequence[float]) -> List[str]:
|
||||
import math
|
||||
|
@ -697,7 +694,6 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase:
|
|||
``approx`` falls back to strict equality for nonnumeric types instead
|
||||
of raising ``TypeError``.
|
||||
"""
|
||||
|
||||
# Delegate the comparison to a class that knows how to deal with the type
|
||||
# of the expected value (e.g. int, float, list, dict, numpy.array, etc).
|
||||
#
|
||||
|
@ -779,7 +775,8 @@ def raises(
|
|||
expected_exception: Union[Type[E], Tuple[Type[E], ...]],
|
||||
*,
|
||||
match: Optional[Union[str, Pattern[str]]] = ...,
|
||||
) -> "RaisesContext[E]": ...
|
||||
) -> "RaisesContext[E]":
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
|
@ -788,7 +785,8 @@ def raises( # noqa: F811
|
|||
func: Callable[..., Any],
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> _pytest._code.ExceptionInfo[E]: ...
|
||||
) -> _pytest._code.ExceptionInfo[E]:
|
||||
...
|
||||
|
||||
|
||||
def raises( # noqa: F811
|
||||
|
@ -837,10 +835,10 @@ def raises( # noqa: F811
|
|||
The ``match`` argument searches the formatted exception string, which includes any
|
||||
`PEP-678 <https://peps.python.org/pep-0678/>`__ ``__notes__``:
|
||||
|
||||
>>> with pytest.raises(ValueError, match=r'had a note added'): # doctest: +SKIP
|
||||
... e = ValueError("value must be 42")
|
||||
... e.add_note("had a note added")
|
||||
... raise e
|
||||
>>> with pytest.raises(ValueError, match=r"had a note added"): # doctest: +SKIP
|
||||
... e = ValueError("value must be 42")
|
||||
... e.add_note("had a note added")
|
||||
... raise e
|
||||
|
||||
The context manager produces an :class:`ExceptionInfo` object which can be used to inspect the
|
||||
details of the captured exception::
|
||||
|
@ -855,7 +853,7 @@ def raises( # noqa: F811
|
|||
Given that ``pytest.raises`` matches subclasses, be wary of using it to match :class:`Exception` like this::
|
||||
|
||||
with pytest.raises(Exception): # Careful, this will catch ANY exception raised.
|
||||
some_function()
|
||||
some_function()
|
||||
|
||||
Because :class:`Exception` is the base class of almost all exceptions, it is easy for this to hide
|
||||
real bugs, where the user wrote this expecting a specific exception, but some other exception is being
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Record warnings during test function execution."""
|
||||
import re
|
||||
import warnings
|
||||
from pprint import pformat
|
||||
import re
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
|
@ -17,11 +16,13 @@ from typing import Tuple
|
|||
from typing import Type
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
from _pytest.deprecated import check_ispytest
|
||||
from _pytest.fixtures import fixture
|
||||
from _pytest.outcomes import fail
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
|
@ -41,13 +42,15 @@ def recwarn() -> Generator["WarningsRecorder", None, None]:
|
|||
@overload
|
||||
def deprecated_call(
|
||||
*, match: Optional[Union[str, Pattern[str]]] = ...
|
||||
) -> "WarningsRecorder": ...
|
||||
) -> "WarningsRecorder":
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def deprecated_call( # noqa: F811
|
||||
func: Callable[..., T], *args: Any, **kwargs: Any
|
||||
) -> T: ...
|
||||
) -> T:
|
||||
...
|
||||
|
||||
|
||||
def deprecated_call( # noqa: F811
|
||||
|
@ -89,7 +92,8 @@ def warns(
|
|||
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ...,
|
||||
*,
|
||||
match: Optional[Union[str, Pattern[str]]] = ...,
|
||||
) -> "WarningsChecker": ...
|
||||
) -> "WarningsChecker":
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
|
@ -98,7 +102,8 @@ def warns( # noqa: F811
|
|||
func: Callable[..., T],
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> T: ...
|
||||
) -> T:
|
||||
...
|
||||
|
||||
|
||||
def warns( # noqa: F811
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import dataclasses
|
||||
import os
|
||||
from io import StringIO
|
||||
import os
|
||||
from pprint import pprint
|
||||
from typing import Any
|
||||
from typing import cast
|
||||
|
@ -37,6 +37,7 @@ from _pytest.nodes import Collector
|
|||
from _pytest.nodes import Item
|
||||
from _pytest.outcomes import skip
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest.runner import CallInfo
|
||||
|
||||
|
@ -46,7 +47,7 @@ def getworkerinfoline(node):
|
|||
return node._workerinfocache
|
||||
except AttributeError:
|
||||
d = node.workerinfo
|
||||
ver = "%s.%s.%s" % d["version_info"][:3]
|
||||
ver = "{}.{}.{}".format(*d["version_info"][:3])
|
||||
node._workerinfocache = s = "[{}] {} -- Python {} {}".format(
|
||||
d["id"], d["sysplatform"], ver, d["executable"]
|
||||
)
|
||||
|
@ -71,7 +72,8 @@ class BaseReport:
|
|||
|
||||
if TYPE_CHECKING:
|
||||
# Can have arbitrary fields given to __init__().
|
||||
def __getattr__(self, key: str) -> Any: ...
|
||||
def __getattr__(self, key: str) -> Any:
|
||||
...
|
||||
|
||||
def toterminal(self, out: TerminalWriter) -> None:
|
||||
if hasattr(self, "node"):
|
||||
|
@ -313,9 +315,7 @@ class TestReport(BaseReport):
|
|||
self.__dict__.update(extra)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<{} {!r} when={!r} outcome={!r}>".format(
|
||||
self.__class__.__name__, self.nodeid, self.when, self.outcome
|
||||
)
|
||||
return f"<{self.__class__.__name__} {self.nodeid!r} when={self.when!r} outcome={self.outcome!r}>"
|
||||
|
||||
@classmethod
|
||||
def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport":
|
||||
|
@ -430,9 +430,7 @@ class CollectReport(BaseReport):
|
|||
return (self.fspath, None, self.fspath)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<CollectReport {!r} lenresult={} outcome={!r}>".format(
|
||||
self.nodeid, len(self.result), self.outcome
|
||||
)
|
||||
return f"<CollectReport {self.nodeid!r} lenresult={len(self.result)} outcome={self.outcome!r}>"
|
||||
|
||||
|
||||
class CollectErrorRepr(TerminalRepr):
|
||||
|
@ -444,7 +442,7 @@ class CollectErrorRepr(TerminalRepr):
|
|||
|
||||
|
||||
def pytest_report_to_serializable(
|
||||
report: Union[CollectReport, TestReport]
|
||||
report: Union[CollectReport, TestReport],
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
if isinstance(report, (TestReport, CollectReport)):
|
||||
data = report._to_json()
|
||||
|
@ -476,7 +474,7 @@ def _report_to_json(report: BaseReport) -> Dict[str, Any]:
|
|||
"""
|
||||
|
||||
def serialize_repr_entry(
|
||||
entry: Union[ReprEntry, ReprEntryNative]
|
||||
entry: Union[ReprEntry, ReprEntryNative],
|
||||
) -> Dict[str, Any]:
|
||||
data = dataclasses.asdict(entry)
|
||||
for key, value in data.items():
|
||||
|
@ -608,9 +606,9 @@ def _report_kwargs_from_json(reportdict: Dict[str, Any]) -> Dict[str, Any]:
|
|||
description,
|
||||
)
|
||||
)
|
||||
exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = (
|
||||
ExceptionChainRepr(chain)
|
||||
)
|
||||
exception_info: Union[
|
||||
ExceptionChainRepr, ReprExceptionInfo
|
||||
] = ExceptionChainRepr(chain)
|
||||
else:
|
||||
exception_info = ReprExceptionInfo(
|
||||
reprtraceback=reprtraceback,
|
||||
|
|
|
@ -37,6 +37,7 @@ from _pytest.outcomes import OutcomeException
|
|||
from _pytest.outcomes import Skipped
|
||||
from _pytest.outcomes import TEST_OUTCOME
|
||||
|
||||
|
||||
if sys.version_info[:2] < (3, 11):
|
||||
from exceptiongroup import BaseExceptionGroup
|
||||
|
||||
|
@ -94,8 +95,7 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None:
|
|||
if verbose < 2 and rep.duration < durations_min:
|
||||
tr.write_line("")
|
||||
tr.write_line(
|
||||
"(%s durations < %gs hidden. Use -vv to show these durations.)"
|
||||
% (len(dlist) - i, durations_min)
|
||||
f"({len(dlist) - i} durations < {durations_min:g}s hidden. Use -vv to show these durations.)"
|
||||
)
|
||||
break
|
||||
tr.write_line(f"{rep.duration:02.2f}s {rep.when:<8} {rep.nodeid}")
|
||||
|
|
|
@ -13,6 +13,7 @@ from functools import total_ordering
|
|||
from typing import Literal
|
||||
from typing import Optional
|
||||
|
||||
|
||||
_ScopeName = Literal["session", "package", "module", "class", "function"]
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ from typing import Generator
|
|||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
import pytest
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
|
@ -10,6 +9,7 @@ from _pytest.config.argparsing import Parser
|
|||
from _pytest.fixtures import FixtureDef
|
||||
from _pytest.fixtures import SubRequest
|
||||
from _pytest.scope import Scope
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_addoption(parser: Parser) -> None:
|
||||
|
@ -74,7 +74,7 @@ def _show_fixture_action(
|
|||
scope_indent = list(reversed(Scope)).index(fixturedef._scope)
|
||||
tw.write(" " * 2 * scope_indent)
|
||||
tw.write(
|
||||
"{step} {scope} {fixture}".format(
|
||||
"{step} {scope} {fixture}".format( # noqa: UP032 (Readability)
|
||||
step=msg.ljust(8), # align the output to TEARDOWN
|
||||
scope=fixturedef.scope[0].upper(),
|
||||
fixture=fixturedef.argname,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
import pytest
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.fixtures import FixtureDef
|
||||
from _pytest.fixtures import SubRequest
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_addoption(parser: Parser) -> None:
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# mypy: allow-untyped-defs
|
||||
"""Support for skip/xfail functions and markers."""
|
||||
from collections.abc import Mapping
|
||||
import dataclasses
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import traceback
|
||||
from collections.abc import Mapping
|
||||
from typing import Generator
|
||||
from typing import Optional
|
||||
from typing import Tuple
|
||||
|
@ -105,9 +105,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool,
|
|||
):
|
||||
if not isinstance(dictionary, Mapping):
|
||||
raise ValueError(
|
||||
"pytest_markeval_namespace() needs to return a dict, got {!r}".format(
|
||||
dictionary
|
||||
)
|
||||
f"pytest_markeval_namespace() needs to return a dict, got {dictionary!r}"
|
||||
)
|
||||
globals_.update(dictionary)
|
||||
if hasattr(item, "obj"):
|
||||
|
|
|
@ -5,6 +5,7 @@ from typing import Generic
|
|||
from typing import TypeVar
|
||||
from typing import Union
|
||||
|
||||
|
||||
__all__ = ["Stash", "StashKey"]
|
||||
|
||||
|
||||
|
|
|
@ -2,12 +2,13 @@ from typing import List
|
|||
from typing import Optional
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
from _pytest import nodes
|
||||
from _pytest.config import Config
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.main import Session
|
||||
from _pytest.reports import TestReport
|
||||
import pytest
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest.cacheprovider import Cache
|
||||
|
|
|
@ -4,16 +4,15 @@
|
|||
This is a good source for looking at the various reporting hooks.
|
||||
"""
|
||||
import argparse
|
||||
from collections import Counter
|
||||
import dataclasses
|
||||
import datetime
|
||||
from functools import partial
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import sys
|
||||
import textwrap
|
||||
import warnings
|
||||
from collections import Counter
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import ClassVar
|
||||
|
@ -31,16 +30,17 @@ from typing import TextIO
|
|||
from typing import Tuple
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
import pluggy
|
||||
|
||||
import _pytest._version
|
||||
from _pytest import nodes
|
||||
from _pytest import timing
|
||||
from _pytest._code import ExceptionInfo
|
||||
from _pytest._code.code import ExceptionRepr
|
||||
from _pytest._io import TerminalWriter
|
||||
from _pytest._io.wcwidth import wcswidth
|
||||
import _pytest._version
|
||||
from _pytest.assertion.util import running_on_ci
|
||||
from _pytest.config import _PluggyPlugin
|
||||
from _pytest.config import Config
|
||||
|
@ -55,6 +55,7 @@ from _pytest.reports import BaseReport
|
|||
from _pytest.reports import CollectReport
|
||||
from _pytest.reports import TestReport
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest.main import Session
|
||||
|
||||
|
@ -671,8 +672,8 @@ class TerminalReporter:
|
|||
return f" [ {collected} / {collected} ]"
|
||||
else:
|
||||
if collected:
|
||||
return " [{:3d}%]".format(
|
||||
len(self._progress_nodeids_reported) * 100 // collected
|
||||
return (
|
||||
f" [{len(self._progress_nodeids_reported) * 100 // collected:3d}%]"
|
||||
)
|
||||
return " [100%]"
|
||||
|
||||
|
@ -757,9 +758,7 @@ class TerminalReporter:
|
|||
if pypy_version_info:
|
||||
verinfo = ".".join(map(str, pypy_version_info[:3]))
|
||||
msg += f"[pypy-{verinfo}-{pypy_version_info[3]}]"
|
||||
msg += ", pytest-{}, pluggy-{}".format(
|
||||
_pytest._version.version, pluggy.__version__
|
||||
)
|
||||
msg += f", pytest-{_pytest._version.version}, pluggy-{pluggy.__version__}"
|
||||
if (
|
||||
self.verbosity > 0
|
||||
or self.config.option.debug
|
||||
|
@ -1464,7 +1463,7 @@ def _plugin_nameversions(plugininfo) -> List[str]:
|
|||
values: List[str] = []
|
||||
for plugin, dist in plugininfo:
|
||||
# Gets us name and version!
|
||||
name = "{dist.project_name}-{dist.version}".format(dist=dist)
|
||||
name = f"{dist.project_name}-{dist.version}"
|
||||
# Questionable convenience, but it keeps things short.
|
||||
if name.startswith("pytest-"):
|
||||
name = name[7:]
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import threading
|
||||
import traceback
|
||||
import warnings
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Generator
|
||||
from typing import Optional
|
||||
from typing import Type
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
@ -10,4 +10,5 @@ from time import perf_counter
|
|||
from time import sleep
|
||||
from time import time
|
||||
|
||||
|
||||
__all__ = ["perf_counter", "sleep", "time"]
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
"""Support for providing temporary directories to test functions."""
|
||||
import dataclasses
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
import re
|
||||
from shutil import rmtree
|
||||
import tempfile
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import final
|
||||
|
@ -32,6 +32,7 @@ from _pytest.nodes import Item
|
|||
from _pytest.reports import TestReport
|
||||
from _pytest.stash import StashKey
|
||||
|
||||
|
||||
tmppath_result_key = StashKey[Dict[str, bool]]()
|
||||
RetentionType = Literal["all", "failed", "none"]
|
||||
|
||||
|
@ -268,7 +269,6 @@ def tmp_path(
|
|||
|
||||
The returned object is a :class:`pathlib.Path` object.
|
||||
"""
|
||||
|
||||
path = _mk_tmp(request, tmp_path_factory)
|
||||
yield path
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ from typing import TYPE_CHECKING
|
|||
from typing import Union
|
||||
|
||||
import _pytest._code
|
||||
import pytest
|
||||
from _pytest.compat import getimfunc
|
||||
from _pytest.compat import is_async_function
|
||||
from _pytest.config import hookimpl
|
||||
|
@ -30,6 +29,8 @@ from _pytest.python import Class
|
|||
from _pytest.python import Function
|
||||
from _pytest.python import Module
|
||||
from _pytest.runner import CallInfo
|
||||
import pytest
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import unittest
|
||||
|
@ -203,7 +204,9 @@ class TestCaseFunction(Function):
|
|||
# Unwrap potential exception info (see twisted trial support below).
|
||||
rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo)
|
||||
try:
|
||||
excinfo = _pytest._code.ExceptionInfo[BaseException].from_exc_info(rawexcinfo) # type: ignore[arg-type]
|
||||
excinfo = _pytest._code.ExceptionInfo[BaseException].from_exc_info(
|
||||
rawexcinfo # type: ignore[arg-type]
|
||||
)
|
||||
# Invoke the attributes to trigger storing the traceback
|
||||
# trial causes some issue there.
|
||||
excinfo.value
|
||||
|
@ -223,7 +226,7 @@ class TestCaseFunction(Function):
|
|||
except BaseException:
|
||||
fail(
|
||||
"ERROR: Unknown Incompatible Exception "
|
||||
"representation:\n%r" % (rawexcinfo,),
|
||||
f"representation:\n{rawexcinfo!r}",
|
||||
pytrace=False,
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
|
@ -348,9 +351,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None:
|
|||
# handled internally, and doesn't reach here.
|
||||
unittest = sys.modules.get("unittest")
|
||||
if (
|
||||
unittest
|
||||
and call.excinfo
|
||||
and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined]
|
||||
unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined]
|
||||
):
|
||||
excinfo = call.excinfo
|
||||
call2 = CallInfo[None].from_call(
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import sys
|
||||
import traceback
|
||||
import warnings
|
||||
from types import TracebackType
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Generator
|
||||
from typing import Optional
|
||||
from typing import Type
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import dataclasses
|
||||
import inspect
|
||||
import warnings
|
||||
from types import FunctionType
|
||||
from typing import Any
|
||||
from typing import final
|
||||
from typing import Generic
|
||||
from typing import Type
|
||||
from typing import TypeVar
|
||||
import warnings
|
||||
|
||||
|
||||
class PytestWarning(UserWarning):
|
||||
|
@ -73,11 +73,7 @@ class PytestExperimentalApiWarning(PytestWarning, FutureWarning):
|
|||
|
||||
@classmethod
|
||||
def simple(cls, apiname: str) -> "PytestExperimentalApiWarning":
|
||||
return cls(
|
||||
"{apiname} is an experimental api that may change over time".format(
|
||||
apiname=apiname
|
||||
)
|
||||
)
|
||||
return cls(f"{apiname} is an experimental api that may change over time")
|
||||
|
||||
|
||||
@final
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import sys
|
||||
import warnings
|
||||
from contextlib import contextmanager
|
||||
import sys
|
||||
from typing import Generator
|
||||
from typing import Literal
|
||||
from typing import Optional
|
||||
import warnings
|
||||
|
||||
import pytest
|
||||
from _pytest.config import apply_warning_filters
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import parse_warning_filter
|
||||
from _pytest.main import Session
|
||||
from _pytest.nodes import Item
|
||||
from _pytest.terminal import TerminalReporter
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_configure(config: Config) -> None:
|
||||
|
|
|
@ -6,6 +6,7 @@ import sys
|
|||
import _pytest._py.error as error
|
||||
import _pytest._py.path as path
|
||||
|
||||
|
||||
sys.modules["py.error"] = error
|
||||
sys.modules["py.path"] = path
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ from _pytest.warning_types import PytestUnknownMarkWarning
|
|||
from _pytest.warning_types import PytestUnraisableExceptionWarning
|
||||
from _pytest.warning_types import PytestWarning
|
||||
|
||||
|
||||
set_trace = __pytestPDB.set_trace
|
||||
|
||||
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
|
||||
import pytest
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(pytest.console_main())
|
||||
|
|
|
@ -4,8 +4,8 @@ import multiprocessing
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
from unittest import mock
|
||||
import warnings
|
||||
|
||||
from py import error
|
||||
from py.path import local
|
||||
|
@ -183,7 +183,7 @@ class CommonFSTests:
|
|||
def test_listdir_filter(self, path1):
|
||||
p = path1.listdir(lambda x: x.check(dir=1))
|
||||
assert path1.join("sampledir") in p
|
||||
assert not path1.join("samplefile") in p
|
||||
assert path1.join("samplefile") not in p
|
||||
|
||||
def test_listdir_sorted(self, path1):
|
||||
p = path1.listdir(lambda x: x.check(basestarts="sample"), sort=True)
|
||||
|
@ -203,7 +203,7 @@ class CommonFSTests:
|
|||
for i in path1.visit(None, lambda x: x.basename != "sampledir"):
|
||||
lst.append(i.relto(path1))
|
||||
assert "sampledir" in lst
|
||||
assert not path1.sep.join(["sampledir", "otherfile"]) in lst
|
||||
assert path1.sep.join(["sampledir", "otherfile"]) not in lst
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fil",
|
||||
|
|
|
@ -6,10 +6,10 @@ import subprocess
|
|||
import sys
|
||||
import types
|
||||
|
||||
import pytest
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.pathlib import symlink_or_skip
|
||||
from _pytest.pytester import Pytester
|
||||
import pytest
|
||||
|
||||
|
||||
def prepend_pythonpath(*dirs) -> str:
|
||||
|
|
|
@ -4,13 +4,13 @@ import sys
|
|||
from types import FrameType
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from _pytest._code import Code
|
||||
from _pytest._code import ExceptionInfo
|
||||
from _pytest._code import Frame
|
||||
from _pytest._code import Source
|
||||
from _pytest._code.code import ExceptionChainRepr
|
||||
from _pytest._code.code import ReprFuncArgs
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ne() -> None:
|
||||
|
|
|
@ -4,16 +4,15 @@ from __future__ import annotations
|
|||
import importlib
|
||||
import io
|
||||
import operator
|
||||
from pathlib import Path
|
||||
import queue
|
||||
import re
|
||||
import sys
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _pytest._code
|
||||
import pytest
|
||||
from _pytest._code.code import ExceptionChainRepr
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
from _pytest._code.code import FormattedExcinfo
|
||||
|
@ -23,6 +22,8 @@ from _pytest.pathlib import bestrelpath
|
|||
from _pytest.pathlib import import_path
|
||||
from _pytest.pytester import LineMatcher
|
||||
from _pytest.pytester import Pytester
|
||||
import pytest
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from _pytest._code.code import _TracebackStyle
|
||||
|
@ -1173,9 +1174,7 @@ raise ValueError()
|
|||
"funcargs": funcargs,
|
||||
"tbfilter": tbfilter,
|
||||
},
|
||||
id="style={},showlocals={},funcargs={},tbfilter={}".format(
|
||||
style, showlocals, funcargs, tbfilter
|
||||
),
|
||||
id=f"style={style},showlocals={showlocals},funcargs={funcargs},tbfilter={tbfilter}",
|
||||
)
|
||||
for style in ["long", "short", "line", "no", "native", "value", "auto"]
|
||||
for showlocals in (True, False)
|
||||
|
@ -1339,7 +1338,7 @@ raise ValueError()
|
|||
"""
|
||||
raise_suffix = " from None" if mode == "from_none" else ""
|
||||
mod = importasmod(
|
||||
"""
|
||||
f"""
|
||||
def f():
|
||||
try:
|
||||
g()
|
||||
|
@ -1347,9 +1346,7 @@ raise ValueError()
|
|||
raise AttributeError(){raise_suffix}
|
||||
def g():
|
||||
raise ValueError()
|
||||
""".format(
|
||||
raise_suffix=raise_suffix
|
||||
)
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(AttributeError, mod.f)
|
||||
r = excinfo.getrepr(style="long", chain=mode != "explicit_suppress")
|
||||
|
@ -1361,9 +1358,7 @@ raise ValueError()
|
|||
assert tw_mock.lines[2] == " try:"
|
||||
assert tw_mock.lines[3] == " g()"
|
||||
assert tw_mock.lines[4] == " except Exception:"
|
||||
assert tw_mock.lines[5] == "> raise AttributeError(){}".format(
|
||||
raise_suffix
|
||||
)
|
||||
assert tw_mock.lines[5] == f"> raise AttributeError(){raise_suffix}"
|
||||
assert tw_mock.lines[6] == "E AttributeError"
|
||||
assert tw_mock.lines[7] == ""
|
||||
line = tw_mock.get_write_msg(8)
|
||||
|
@ -1394,7 +1389,7 @@ raise ValueError()
|
|||
"""
|
||||
exc_handling_code = " from e" if reason == "cause" else ""
|
||||
mod = importasmod(
|
||||
"""
|
||||
f"""
|
||||
def f():
|
||||
try:
|
||||
g()
|
||||
|
@ -1402,9 +1397,7 @@ raise ValueError()
|
|||
raise RuntimeError('runtime problem'){exc_handling_code}
|
||||
def g():
|
||||
raise ValueError('invalid value')
|
||||
""".format(
|
||||
exc_handling_code=exc_handling_code
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
|
|
|
@ -5,9 +5,10 @@ import sys
|
|||
from typing import Generator
|
||||
from typing import List
|
||||
|
||||
import pytest
|
||||
from _pytest.monkeypatch import MonkeyPatch
|
||||
from _pytest.pytester import Pytester
|
||||
import pytest
|
||||
|
||||
|
||||
if sys.gettrace():
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import pytest
|
||||
from _pytest import deprecated
|
||||
from _pytest.pytester import Pytester
|
||||
import pytest
|
||||
from pytest import PytestDeprecationWarning
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from unittest import mock
|
|||
|
||||
import pytest
|
||||
|
||||
|
||||
config = {"mykey": "ORIGINAL"}
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import argparse
|
||||
import pathlib
|
||||
|
||||
|
||||
HERE = pathlib.Path(__file__).parent
|
||||
TEST_CONTENT = (HERE / "template_test.py").read_bytes()
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from typing import List
|
||||
from unittest import IsolatedAsyncioTestCase
|
||||
|
||||
|
||||
teardowns: List[None] = []
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ from typing import List
|
|||
|
||||
import asynctest
|
||||
|
||||
|
||||
teardowns: List[None] = []
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import textwrap
|
||||
from collections import ChainMap
|
||||
from collections import Counter
|
||||
from collections import defaultdict
|
||||
from collections import deque
|
||||
from collections import OrderedDict
|
||||
from dataclasses import dataclass
|
||||
import textwrap
|
||||
from types import MappingProxyType
|
||||
from types import SimpleNamespace
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from _pytest._io.pprint import PrettyPrinter
|
||||
import pytest
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import pytest
|
||||
from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE
|
||||
from _pytest._io.saferepr import saferepr
|
||||
from _pytest._io.saferepr import saferepr_unlimited
|
||||
import pytest
|
||||
|
||||
|
||||
def test_simple_repr():
|
||||
|
@ -59,9 +59,7 @@ def test_exceptions() -> None:
|
|||
obj = BrokenRepr(BrokenReprException("omg even worse"))
|
||||
s2 = saferepr(obj)
|
||||
assert s2 == (
|
||||
"<[unpresentable exception ({!s}) raised in repr()] BrokenRepr object at 0x{:x}>".format(
|
||||
exp_exc, id(obj)
|
||||
)
|
||||
f"<[unpresentable exception ({exp_exc!s}) raised in repr()] BrokenRepr object at 0x{id(obj):x}>"
|
||||
)
|
||||
|
||||
|
||||
|
@ -99,14 +97,12 @@ def test_baseexception():
|
|||
baseexc_str = BaseException("__str__")
|
||||
obj = BrokenObj(RaisingOnStrRepr([BaseException]))
|
||||
assert saferepr(obj) == (
|
||||
"<[unpresentable exception ({!r}) "
|
||||
"raised in repr()] BrokenObj object at 0x{:x}>".format(baseexc_str, id(obj))
|
||||
f"<[unpresentable exception ({baseexc_str!r}) "
|
||||
f"raised in repr()] BrokenObj object at 0x{id(obj):x}>"
|
||||
)
|
||||
obj = BrokenObj(RaisingOnStrRepr([RaisingOnStrRepr([BaseException])]))
|
||||
assert saferepr(obj) == (
|
||||
"<[{!r} raised in repr()] BrokenObj object at 0x{:x}>".format(
|
||||
baseexc_str, id(obj)
|
||||
)
|
||||
f"<[{baseexc_str!r} raised in repr()] BrokenObj object at 0x{id(obj):x}>"
|
||||
)
|
||||
|
||||
with pytest.raises(KeyboardInterrupt):
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import io
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Generator
|
||||
from typing import Optional
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from _pytest._io import terminalwriter
|
||||
from _pytest.monkeypatch import MonkeyPatch
|
||||
import pytest
|
||||
|
||||
|
||||
# These tests were initially copied from py 1.8.1.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
from _pytest._io.wcwidth import wcswidth
|
||||
from _pytest._io.wcwidth import wcwidth
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
import logging
|
||||
from typing import Iterator
|
||||
|
||||
import pytest
|
||||
from _pytest.logging import caplog_records_key
|
||||
from _pytest.pytester import Pytester
|
||||
import pytest
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
sublogger = logging.getLogger(__name__ + ".baz")
|
||||
|
|
|
@ -4,12 +4,12 @@ import os
|
|||
import re
|
||||
from typing import cast
|
||||
|
||||
import pytest
|
||||
from _pytest.capture import CaptureManager
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.fixtures import FixtureRequest
|
||||
from _pytest.pytester import Pytester
|
||||
from _pytest.terminal import TerminalReporter
|
||||
import pytest
|
||||
|
||||
|
||||
def test_nothing_logged(pytester: Pytester) -> None:
|
||||
|
@ -177,13 +177,11 @@ def test_teardown_logging(pytester: Pytester) -> None:
|
|||
def test_log_cli_enabled_disabled(pytester: Pytester, enabled: bool) -> None:
|
||||
msg = "critical message logged by test"
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
f"""
|
||||
import logging
|
||||
def test_log_cli():
|
||||
logging.critical("{}")
|
||||
""".format(
|
||||
msg
|
||||
)
|
||||
logging.critical("{msg}")
|
||||
"""
|
||||
)
|
||||
if enabled:
|
||||
pytester.makeini(
|
||||
|
@ -710,13 +708,11 @@ def test_log_file_ini(pytester: Pytester) -> None:
|
|||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makeini(
|
||||
"""
|
||||
f"""
|
||||
[pytest]
|
||||
log_file={}
|
||||
log_file={log_file}
|
||||
log_file_level=WARNING
|
||||
""".format(
|
||||
log_file
|
||||
)
|
||||
"""
|
||||
)
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
|
@ -749,13 +745,11 @@ def test_log_file_ini_level(pytester: Pytester) -> None:
|
|||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makeini(
|
||||
"""
|
||||
f"""
|
||||
[pytest]
|
||||
log_file={}
|
||||
log_file={log_file}
|
||||
log_file_level = INFO
|
||||
""".format(
|
||||
log_file
|
||||
)
|
||||
"""
|
||||
)
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
|
@ -788,13 +782,11 @@ def test_log_file_unicode(pytester: Pytester) -> None:
|
|||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makeini(
|
||||
"""
|
||||
f"""
|
||||
[pytest]
|
||||
log_file={}
|
||||
log_file={log_file}
|
||||
log_file_level = INFO
|
||||
""".format(
|
||||
log_file
|
||||
)
|
||||
"""
|
||||
)
|
||||
pytester.makepyfile(
|
||||
"""\
|
||||
|
@ -832,8 +824,8 @@ def test_live_logging_suspends_capture(
|
|||
is installed.
|
||||
"""
|
||||
import contextlib
|
||||
import logging
|
||||
from functools import partial
|
||||
import logging
|
||||
|
||||
from _pytest.logging import _LiveLoggingStreamHandler
|
||||
|
||||
|
@ -924,13 +916,11 @@ def test_collection_logging_to_file(pytester: Pytester) -> None:
|
|||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makeini(
|
||||
"""
|
||||
f"""
|
||||
[pytest]
|
||||
log_file={}
|
||||
log_file={log_file}
|
||||
log_file_level = INFO
|
||||
""".format(
|
||||
log_file
|
||||
)
|
||||
"""
|
||||
)
|
||||
|
||||
pytester.makepyfile(
|
||||
|
@ -962,14 +952,12 @@ def test_log_in_hooks(pytester: Pytester) -> None:
|
|||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makeini(
|
||||
"""
|
||||
f"""
|
||||
[pytest]
|
||||
log_file={}
|
||||
log_file={log_file}
|
||||
log_file_level = INFO
|
||||
log_cli=true
|
||||
""".format(
|
||||
log_file
|
||||
)
|
||||
"""
|
||||
)
|
||||
pytester.makeconftest(
|
||||
"""
|
||||
|
@ -998,14 +986,12 @@ def test_log_in_runtest_logreport(pytester: Pytester) -> None:
|
|||
log_file = str(pytester.path.joinpath("pytest.log"))
|
||||
|
||||
pytester.makeini(
|
||||
"""
|
||||
f"""
|
||||
[pytest]
|
||||
log_file={}
|
||||
log_file={log_file}
|
||||
log_file_level = INFO
|
||||
log_cli=true
|
||||
""".format(
|
||||
log_file
|
||||
)
|
||||
"""
|
||||
)
|
||||
pytester.makeconftest(
|
||||
"""
|
||||
|
@ -1039,19 +1025,17 @@ def test_log_set_path(pytester: Pytester) -> None:
|
|||
"""
|
||||
)
|
||||
pytester.makeconftest(
|
||||
"""
|
||||
f"""
|
||||
import os
|
||||
import pytest
|
||||
@pytest.hookimpl(wrapper=True, tryfirst=True)
|
||||
def pytest_runtest_setup(item):
|
||||
config = item.config
|
||||
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
|
||||
report_file = os.path.join({}, item._request.node.name)
|
||||
report_file = os.path.join({repr(report_dir_base)}, item._request.node.name)
|
||||
logging_plugin.set_log_path(report_file)
|
||||
return (yield)
|
||||
""".format(
|
||||
repr(report_dir_base)
|
||||
)
|
||||
"""
|
||||
)
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import operator
|
||||
from contextlib import contextmanager
|
||||
from decimal import Decimal
|
||||
from fractions import Fraction
|
||||
from math import sqrt
|
||||
import operator
|
||||
from operator import eq
|
||||
from operator import ne
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from _pytest.pytester import Pytester
|
||||
from _pytest.python_api import _recursive_sequence_map
|
||||
import pytest
|
||||
from pytest import approx
|
||||
|
||||
|
||||
inf, nan = float("inf"), float("nan")
|
||||
|
||||
|
||||
|
@ -38,9 +39,7 @@ def mocked_doctest_runner(monkeypatch):
|
|||
class MyDocTestRunner(doctest.DocTestRunner):
|
||||
def report_failure(self, out, test, example, got):
|
||||
raise AssertionError(
|
||||
"'{}' evaluates to '{}', not '{}'".format(
|
||||
example.source.strip(), got.strip(), example.want.strip()
|
||||
)
|
||||
f"'{example.source.strip()}' evaluates to '{got.strip()}', not '{example.want.strip()}'"
|
||||
)
|
||||
|
||||
return MyDocTestRunner()
|
||||
|
|
|
@ -6,7 +6,6 @@ from typing import Any
|
|||
from typing import Dict
|
||||
|
||||
import _pytest._code
|
||||
import pytest
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.main import Session
|
||||
from _pytest.monkeypatch import MonkeyPatch
|
||||
|
@ -14,6 +13,7 @@ from _pytest.nodes import Collector
|
|||
from _pytest.pytester import Pytester
|
||||
from _pytest.python import Class
|
||||
from _pytest.python import Function
|
||||
import pytest
|
||||
|
||||
|
||||
class TestModule:
|
||||
|
@ -54,13 +54,11 @@ class TestModule:
|
|||
monkeypatch.syspath_prepend(str(root1))
|
||||
p.write_text(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
f"""\
|
||||
import x456
|
||||
def test():
|
||||
assert x456.__file__.startswith({!r})
|
||||
""".format(
|
||||
str(root2)
|
||||
)
|
||||
assert x456.__file__.startswith({str(root2)!r})
|
||||
"""
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from _pytest.compat import getfuncargnames
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.fixtures import deduplicate_names
|
||||
|
@ -13,6 +12,7 @@ from _pytest.monkeypatch import MonkeyPatch
|
|||
from _pytest.pytester import get_public_names
|
||||
from _pytest.pytester import Pytester
|
||||
from _pytest.python import Function
|
||||
import pytest
|
||||
|
||||
|
||||
def test_getfuncargnames_functions():
|
||||
|
@ -1288,7 +1288,7 @@ class TestFixtureUsages:
|
|||
@pytest.mark.parametrize("scope", ["function", "session"])
|
||||
def test_parameters_without_eq_semantics(self, scope, pytester: Pytester) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
f"""
|
||||
class NoEq1: # fails on `a == b` statement
|
||||
def __eq__(self, _):
|
||||
raise RuntimeError
|
||||
|
@ -1310,9 +1310,7 @@ class TestFixtureUsages:
|
|||
|
||||
def test2(no_eq):
|
||||
pass
|
||||
""".format(
|
||||
scope=scope
|
||||
)
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest()
|
||||
result.stdout.fnmatch_lines(["*4 passed*"])
|
||||
|
@ -2199,7 +2197,7 @@ class TestAutouseManagement:
|
|||
pass
|
||||
def test_check():
|
||||
assert values == ["new1", "new2", "fin2", "fin1"]
|
||||
"""
|
||||
""" # noqa: UP031 (python syntax issues)
|
||||
% locals()
|
||||
)
|
||||
reprec = pytester.inline_run("-s")
|
||||
|
@ -3087,8 +3085,8 @@ class TestFixtureMarker:
|
|||
pass
|
||||
def test_other():
|
||||
pass
|
||||
"""
|
||||
% {"scope": scope}
|
||||
""" # noqa: UP031 (python syntax issues)
|
||||
% {"scope": scope} # noqa: UP031 (python syntax issues)
|
||||
)
|
||||
reprec = pytester.inline_run("-lvs")
|
||||
reprec.assertoutcome(passed=3)
|
||||
|
@ -3287,7 +3285,7 @@ class TestRequestScopeAccess:
|
|||
assert request.config
|
||||
def test_func():
|
||||
pass
|
||||
"""
|
||||
""" # noqa: UP031 (python syntax issues)
|
||||
% (scope, ok.split(), error.split())
|
||||
)
|
||||
reprec = pytester.inline_run("-l")
|
||||
|
@ -3308,7 +3306,7 @@ class TestRequestScopeAccess:
|
|||
assert request.config
|
||||
def test_func(arg):
|
||||
pass
|
||||
"""
|
||||
""" # noqa: UP031 (python syntax issues)
|
||||
% (scope, ok.split(), error.split())
|
||||
)
|
||||
reprec = pytester.inline_run()
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# mypy: allow-untyped-defs
|
||||
import pytest
|
||||
from _pytest._code import getfslineno
|
||||
from _pytest.fixtures import getfixturemarker
|
||||
from _pytest.pytester import Pytester
|
||||
from _pytest.python import Function
|
||||
import pytest
|
||||
|
||||
|
||||
def test_wrapped_getfslineno() -> None:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue