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:
Pierre Sassoulas 2024-01-31 21:12:33 +01:00
parent 046f64751b
commit 4588653b24
149 changed files with 799 additions and 971 deletions

View File

@ -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:

View File

@ -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

View File

@ -1,5 +1,6 @@
import sys
if __name__ == "__main__":
import cProfile
import pstats

View File

@ -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",

View File

@ -1,5 +1,6 @@
import pytest
SKIP = True

View File

@ -1,5 +1,6 @@
from unittest import TestCase # noqa: F401
for i in range(15000):
exec(
f"""

View File

@ -23,6 +23,7 @@ from typing import TYPE_CHECKING
from _pytest import __version__ as version
if TYPE_CHECKING:
import sphinx.application

View File

@ -2,6 +2,7 @@ import os.path
import pytest
mydir = os.path.dirname(__file__)

View 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",)

View File

@ -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)

View File

@ -1,5 +1,6 @@
import pytest
xfail = pytest.mark.xfail

View File

@ -3,6 +3,7 @@ from pathlib import Path
import requests
issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,6 +1,6 @@
# mypy: disallow-untyped-defs
import sys
from subprocess import call
import sys
def main() -> int:

View File

@ -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"""

View File

@ -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

View File

@ -10,6 +10,7 @@ from .code import TracebackEntry
from .source import getrawcode
from .source import Source
__all__ = [
"Code",
"ExceptionInfo",

View File

@ -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

View File

@ -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):

View File

@ -1,6 +1,7 @@
from .terminalwriter import get_terminal_width
from .terminalwriter import TerminalWriter
__all__ = [
"TerminalWriter",
"get_terminal_width",

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -1,5 +1,5 @@
import unicodedata
from functools import lru_cache
import unicodedata
@lru_cache(100)

View File

@ -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

View File

@ -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)

View File

@ -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]:

View File

@ -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})"

View File

@ -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"

View File

@ -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]

View File

@ -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":

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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 {}

View File

@ -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}")

View File

@ -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 = {

View File

@ -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

View File

@ -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]()

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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}"
)

View File

@ -27,6 +27,7 @@ from typing import NoReturn
from typing import Optional
from typing import Sequence
__all__ = [
"Expression",
"ParseError",

View File

@ -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``.
"""

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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]]()

View File

@ -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"
)

View File

@ -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()

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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}")

View File

@ -13,6 +13,7 @@ from functools import total_ordering
from typing import Literal
from typing import Optional
_ScopeName = Literal["session", "package", "module", "class", "function"]

View File

@ -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,

View File

@ -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:

View File

@ -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"):

View File

@ -5,6 +5,7 @@ from typing import Generic
from typing import TypeVar
from typing import Union
__all__ = ["Stash", "StashKey"]

View File

@ -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

View File

@ -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:]

View File

@ -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

View File

@ -10,4 +10,5 @@ from time import perf_counter
from time import sleep
from time import time
__all__ = ["perf_counter", "sleep", "time"]

View File

@ -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

View File

@ -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(

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -2,5 +2,6 @@
import pytest
if __name__ == "__main__":
raise SystemExit(pytest.console_main())

View File

@ -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",

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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():

View File

@ -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

View File

@ -4,6 +4,7 @@ from unittest import mock
import pytest
config = {"mykey": "ORIGINAL"}

View File

@ -2,6 +2,7 @@
import argparse
import pathlib
HERE = pathlib.Path(__file__).parent
TEST_CONTENT = (HERE / "template_test.py").read_bytes()

View File

@ -2,6 +2,7 @@
from typing import List
from unittest import IsolatedAsyncioTestCase
teardowns: List[None] = []

View File

@ -5,6 +5,7 @@ from typing import List
import asynctest
teardowns: List[None] = []

View File

@ -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

View File

@ -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):

View File

@ -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.

View File

@ -1,6 +1,6 @@
import pytest
from _pytest._io.wcwidth import wcswidth
from _pytest._io.wcwidth import wcwidth
import pytest
@pytest.mark.parametrize(

View File

@ -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")

View File

@ -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(
"""

View File

@ -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()

View File

@ -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",
)

View File

@ -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()

View File

@ -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