mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-09 21:04:17 +00:00
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
72ad6dc953
commit
f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions
|
|
@ -1,4 +1,5 @@
|
|||
"""Generic mechanism for marking and selecting python functions."""
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
from typing import AbstractSet
|
||||
|
|
@ -8,6 +9,13 @@ from typing import Optional
|
|||
from typing import TYPE_CHECKING
|
||||
from typing import Union
|
||||
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.config import hookimpl
|
||||
from _pytest.config import UsageError
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.stash import StashKey
|
||||
|
||||
from .expression import Expression
|
||||
from .expression import ParseError
|
||||
from .structures import EMPTY_PARAMETERSET_OPTION
|
||||
|
|
@ -17,12 +25,6 @@ from .structures import MARK_GEN
|
|||
from .structures import MarkDecorator
|
||||
from .structures import MarkGenerator
|
||||
from .structures import ParameterSet
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.config import hookimpl
|
||||
from _pytest.config import UsageError
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.stash import StashKey
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -30,12 +32,12 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
__all__ = [
|
||||
"MARK_GEN",
|
||||
"Mark",
|
||||
"MarkDecorator",
|
||||
"MarkGenerator",
|
||||
"ParameterSet",
|
||||
"get_empty_parameterset_mark",
|
||||
'MARK_GEN',
|
||||
'Mark',
|
||||
'MarkDecorator',
|
||||
'MarkGenerator',
|
||||
'ParameterSet',
|
||||
'get_empty_parameterset_mark',
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -44,8 +46,8 @@ old_mark_config_key = StashKey[Optional[Config]]()
|
|||
|
||||
def param(
|
||||
*values: object,
|
||||
marks: Union[MarkDecorator, Collection[Union[MarkDecorator, Mark]]] = (),
|
||||
id: Optional[str] = None,
|
||||
marks: MarkDecorator | Collection[MarkDecorator | Mark] = (),
|
||||
id: str | None = None,
|
||||
) -> ParameterSet:
|
||||
"""Specify a parameter in `pytest.mark.parametrize`_ calls or
|
||||
:ref:`parametrized fixtures <fixture-parametrize-marks>`.
|
||||
|
|
@ -70,59 +72,59 @@ def param(
|
|||
|
||||
|
||||
def pytest_addoption(parser: Parser) -> None:
|
||||
group = parser.getgroup("general")
|
||||
group = parser.getgroup('general')
|
||||
group._addoption(
|
||||
"-k",
|
||||
action="store",
|
||||
dest="keyword",
|
||||
default="",
|
||||
metavar="EXPRESSION",
|
||||
help="Only run tests which match the given substring expression. "
|
||||
"An expression is a Python evaluatable expression "
|
||||
"where all names are substring-matched against test names "
|
||||
'-k',
|
||||
action='store',
|
||||
dest='keyword',
|
||||
default='',
|
||||
metavar='EXPRESSION',
|
||||
help='Only run tests which match the given substring expression. '
|
||||
'An expression is a Python evaluatable expression '
|
||||
'where all names are substring-matched against test names '
|
||||
"and their parent classes. Example: -k 'test_method or test_"
|
||||
"other' matches all test functions and classes whose name "
|
||||
"contains 'test_method' or 'test_other', while -k 'not test_method' "
|
||||
"matches those that don't contain 'test_method' in their names. "
|
||||
"-k 'not test_method and not test_other' will eliminate the matches. "
|
||||
"Additionally keywords are matched to classes and functions "
|
||||
'Additionally keywords are matched to classes and functions '
|
||||
"containing extra names in their 'extra_keyword_matches' set, "
|
||||
"as well as functions which have names assigned directly to them. "
|
||||
"The matching is case-insensitive.",
|
||||
'as well as functions which have names assigned directly to them. '
|
||||
'The matching is case-insensitive.',
|
||||
)
|
||||
|
||||
group._addoption(
|
||||
"-m",
|
||||
action="store",
|
||||
dest="markexpr",
|
||||
default="",
|
||||
metavar="MARKEXPR",
|
||||
help="Only run tests matching given mark expression. "
|
||||
'-m',
|
||||
action='store',
|
||||
dest='markexpr',
|
||||
default='',
|
||||
metavar='MARKEXPR',
|
||||
help='Only run tests matching given mark expression. '
|
||||
"For example: -m 'mark1 and not mark2'.",
|
||||
)
|
||||
|
||||
group.addoption(
|
||||
"--markers",
|
||||
action="store_true",
|
||||
help="show markers (builtin, plugin and per-project ones).",
|
||||
'--markers',
|
||||
action='store_true',
|
||||
help='show markers (builtin, plugin and per-project ones).',
|
||||
)
|
||||
|
||||
parser.addini("markers", "Register new markers for test functions", "linelist")
|
||||
parser.addini(EMPTY_PARAMETERSET_OPTION, "Default marker for empty parametersets")
|
||||
parser.addini('markers', 'Register new markers for test functions', 'linelist')
|
||||
parser.addini(EMPTY_PARAMETERSET_OPTION, 'Default marker for empty parametersets')
|
||||
|
||||
|
||||
@hookimpl(tryfirst=True)
|
||||
def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]:
|
||||
def pytest_cmdline_main(config: Config) -> int | ExitCode | None:
|
||||
import _pytest.config
|
||||
|
||||
if config.option.markers:
|
||||
config._do_configure()
|
||||
tw = _pytest.config.create_terminal_writer(config)
|
||||
for line in config.getini("markers"):
|
||||
parts = line.split(":", 1)
|
||||
for line in config.getini('markers'):
|
||||
parts = line.split(':', 1)
|
||||
name = parts[0]
|
||||
rest = parts[1] if len(parts) == 2 else ""
|
||||
tw.write("@pytest.mark.%s:" % name, bold=True)
|
||||
rest = parts[1] if len(parts) == 2 else ''
|
||||
tw.write('@pytest.mark.%s:' % name, bold=True)
|
||||
tw.line(rest)
|
||||
tw.line()
|
||||
config._ensure_unconfigure()
|
||||
|
|
@ -146,12 +148,12 @@ class KeywordMatcher:
|
|||
any item, as well as names directly assigned to test functions.
|
||||
"""
|
||||
|
||||
__slots__ = ("_names",)
|
||||
__slots__ = ('_names',)
|
||||
|
||||
_names: AbstractSet[str]
|
||||
|
||||
@classmethod
|
||||
def from_item(cls, item: "Item") -> "KeywordMatcher":
|
||||
def from_item(cls, item: Item) -> KeywordMatcher:
|
||||
mapped_names = set()
|
||||
|
||||
# Add the names of the current item and any parent items,
|
||||
|
|
@ -163,7 +165,7 @@ class KeywordMatcher:
|
|||
if isinstance(node, pytest.Session):
|
||||
continue
|
||||
if isinstance(node, pytest.Directory) and isinstance(
|
||||
node.parent, pytest.Session
|
||||
node.parent, pytest.Session,
|
||||
):
|
||||
continue
|
||||
mapped_names.add(node.name)
|
||||
|
|
@ -172,7 +174,7 @@ class KeywordMatcher:
|
|||
mapped_names.update(item.listextrakeywords())
|
||||
|
||||
# Add the names attached to the current function through direct assignment.
|
||||
function_obj = getattr(item, "function", None)
|
||||
function_obj = getattr(item, 'function', None)
|
||||
if function_obj:
|
||||
mapped_names.update(function_obj.__dict__)
|
||||
|
||||
|
|
@ -191,7 +193,7 @@ class KeywordMatcher:
|
|||
return False
|
||||
|
||||
|
||||
def deselect_by_keyword(items: "List[Item]", config: Config) -> None:
|
||||
def deselect_by_keyword(items: List[Item], config: Config) -> None:
|
||||
keywordexpr = config.option.keyword.lstrip()
|
||||
if not keywordexpr:
|
||||
return
|
||||
|
|
@ -218,12 +220,12 @@ class MarkMatcher:
|
|||
Tries to match on any marker names, attached to the given colitem.
|
||||
"""
|
||||
|
||||
__slots__ = ("own_mark_names",)
|
||||
__slots__ = ('own_mark_names',)
|
||||
|
||||
own_mark_names: AbstractSet[str]
|
||||
|
||||
@classmethod
|
||||
def from_item(cls, item: "Item") -> "MarkMatcher":
|
||||
def from_item(cls, item: Item) -> MarkMatcher:
|
||||
mark_names = {mark.name for mark in item.iter_markers()}
|
||||
return cls(mark_names)
|
||||
|
||||
|
|
@ -231,14 +233,14 @@ class MarkMatcher:
|
|||
return name in self.own_mark_names
|
||||
|
||||
|
||||
def deselect_by_mark(items: "List[Item]", config: Config) -> None:
|
||||
def deselect_by_mark(items: List[Item], config: Config) -> None:
|
||||
matchexpr = config.option.markexpr
|
||||
if not matchexpr:
|
||||
return
|
||||
|
||||
expr = _parse_expression(matchexpr, "Wrong expression passed to '-m'")
|
||||
remaining: List[Item] = []
|
||||
deselected: List[Item] = []
|
||||
remaining: list[Item] = []
|
||||
deselected: list[Item] = []
|
||||
for item in items:
|
||||
if expr.evaluate(MarkMatcher.from_item(item)):
|
||||
remaining.append(item)
|
||||
|
|
@ -253,10 +255,10 @@ def _parse_expression(expr: str, exc_message: str) -> Expression:
|
|||
try:
|
||||
return Expression.compile(expr)
|
||||
except ParseError as e:
|
||||
raise UsageError(f"{exc_message}: {expr}: {e}") from None
|
||||
raise UsageError(f'{exc_message}: {expr}: {e}') from None
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(items: "List[Item]", config: Config) -> None:
|
||||
def pytest_collection_modifyitems(items: List[Item], config: Config) -> None:
|
||||
deselect_by_keyword(items, config)
|
||||
deselect_by_mark(items, config)
|
||||
|
||||
|
|
@ -267,10 +269,10 @@ def pytest_configure(config: Config) -> None:
|
|||
|
||||
empty_parameterset = config.getini(EMPTY_PARAMETERSET_OPTION)
|
||||
|
||||
if empty_parameterset not in ("skip", "xfail", "fail_at_collect", None, ""):
|
||||
if empty_parameterset not in ('skip', 'xfail', 'fail_at_collect', None, ''):
|
||||
raise UsageError(
|
||||
f"{EMPTY_PARAMETERSET_OPTION!s} must be one of skip, xfail or fail_at_collect"
|
||||
f" but it is {empty_parameterset!r}"
|
||||
f'{EMPTY_PARAMETERSET_OPTION!s} must be one of skip, xfail or fail_at_collect'
|
||||
f' but it is {empty_parameterset!r}',
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ The semantics are:
|
|||
- ident evaluates to True of False according to a provided matcher function.
|
||||
- or/and/not evaluate according to the usual boolean semantics.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import dataclasses
|
||||
|
|
@ -29,24 +30,24 @@ from typing import Sequence
|
|||
|
||||
|
||||
__all__ = [
|
||||
"Expression",
|
||||
"ParseError",
|
||||
'Expression',
|
||||
'ParseError',
|
||||
]
|
||||
|
||||
|
||||
class TokenType(enum.Enum):
|
||||
LPAREN = "left parenthesis"
|
||||
RPAREN = "right parenthesis"
|
||||
OR = "or"
|
||||
AND = "and"
|
||||
NOT = "not"
|
||||
IDENT = "identifier"
|
||||
EOF = "end of input"
|
||||
LPAREN = 'left parenthesis'
|
||||
RPAREN = 'right parenthesis'
|
||||
OR = 'or'
|
||||
AND = 'and'
|
||||
NOT = 'not'
|
||||
IDENT = 'identifier'
|
||||
EOF = 'end of input'
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class Token:
|
||||
__slots__ = ("type", "value", "pos")
|
||||
__slots__ = ('type', 'value', 'pos')
|
||||
type: TokenType
|
||||
value: str
|
||||
pos: int
|
||||
|
|
@ -64,11 +65,11 @@ class ParseError(Exception):
|
|||
self.message = message
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"at column {self.column}: {self.message}"
|
||||
return f'at column {self.column}: {self.message}'
|
||||
|
||||
|
||||
class Scanner:
|
||||
__slots__ = ("tokens", "current")
|
||||
__slots__ = ('tokens', 'current')
|
||||
|
||||
def __init__(self, input: str) -> None:
|
||||
self.tokens = self.lex(input)
|
||||
|
|
@ -77,23 +78,23 @@ class Scanner:
|
|||
def lex(self, input: str) -> Iterator[Token]:
|
||||
pos = 0
|
||||
while pos < len(input):
|
||||
if input[pos] in (" ", "\t"):
|
||||
if input[pos] in (' ', '\t'):
|
||||
pos += 1
|
||||
elif input[pos] == "(":
|
||||
yield Token(TokenType.LPAREN, "(", pos)
|
||||
elif input[pos] == '(':
|
||||
yield Token(TokenType.LPAREN, '(', pos)
|
||||
pos += 1
|
||||
elif input[pos] == ")":
|
||||
yield Token(TokenType.RPAREN, ")", pos)
|
||||
elif input[pos] == ')':
|
||||
yield Token(TokenType.RPAREN, ')', pos)
|
||||
pos += 1
|
||||
else:
|
||||
match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\|/)+", input[pos:])
|
||||
match = re.match(r'(:?\w|:|\+|-|\.|\[|\]|\\|/)+', input[pos:])
|
||||
if match:
|
||||
value = match.group(0)
|
||||
if value == "or":
|
||||
if value == 'or':
|
||||
yield Token(TokenType.OR, value, pos)
|
||||
elif value == "and":
|
||||
elif value == 'and':
|
||||
yield Token(TokenType.AND, value, pos)
|
||||
elif value == "not":
|
||||
elif value == 'not':
|
||||
yield Token(TokenType.NOT, value, pos)
|
||||
else:
|
||||
yield Token(TokenType.IDENT, value, pos)
|
||||
|
|
@ -103,9 +104,9 @@ class Scanner:
|
|||
pos + 1,
|
||||
f'unexpected character "{input[pos]}"',
|
||||
)
|
||||
yield Token(TokenType.EOF, "", pos)
|
||||
yield Token(TokenType.EOF, '', pos)
|
||||
|
||||
def accept(self, type: TokenType, *, reject: bool = False) -> Optional[Token]:
|
||||
def accept(self, type: TokenType, *, reject: bool = False) -> Token | None:
|
||||
if self.current.type is type:
|
||||
token = self.current
|
||||
if token.type is not TokenType.EOF:
|
||||
|
|
@ -118,8 +119,8 @@ class Scanner:
|
|||
def reject(self, expected: Sequence[TokenType]) -> NoReturn:
|
||||
raise ParseError(
|
||||
self.current.pos + 1,
|
||||
"expected {}; got {}".format(
|
||||
" OR ".join(type.value for type in expected),
|
||||
'expected {}; got {}'.format(
|
||||
' OR '.join(type.value for type in expected),
|
||||
self.current.type.value,
|
||||
),
|
||||
)
|
||||
|
|
@ -128,7 +129,7 @@ class Scanner:
|
|||
# True, False and None are legal match expression identifiers,
|
||||
# but illegal as Python identifiers. To fix this, this prefix
|
||||
# is added to identifiers in the conversion to Python AST.
|
||||
IDENT_PREFIX = "$"
|
||||
IDENT_PREFIX = '$'
|
||||
|
||||
|
||||
def expression(s: Scanner) -> ast.Expression:
|
||||
|
|
@ -176,7 +177,7 @@ class MatcherAdapter(Mapping[str, bool]):
|
|||
self.matcher = matcher
|
||||
|
||||
def __getitem__(self, key: str) -> bool:
|
||||
return self.matcher(key[len(IDENT_PREFIX) :])
|
||||
return self.matcher(key[len(IDENT_PREFIX):])
|
||||
|
||||
def __iter__(self) -> Iterator[str]:
|
||||
raise NotImplementedError()
|
||||
|
|
@ -191,13 +192,13 @@ class Expression:
|
|||
The expression can be evaluated against different matchers.
|
||||
"""
|
||||
|
||||
__slots__ = ("code",)
|
||||
__slots__ = ('code',)
|
||||
|
||||
def __init__(self, code: types.CodeType) -> None:
|
||||
self.code = code
|
||||
|
||||
@classmethod
|
||||
def compile(self, input: str) -> "Expression":
|
||||
def compile(self, input: str) -> Expression:
|
||||
"""Compile a match expression.
|
||||
|
||||
:param input: The input expression - one line.
|
||||
|
|
@ -205,8 +206,8 @@ class Expression:
|
|||
astexpr = expression(Scanner(input))
|
||||
code: types.CodeType = compile(
|
||||
astexpr,
|
||||
filename="<pytest match expression>",
|
||||
mode="eval",
|
||||
filename='<pytest match expression>',
|
||||
mode='eval',
|
||||
)
|
||||
return Expression(code)
|
||||
|
||||
|
|
@ -219,5 +220,5 @@ class Expression:
|
|||
|
||||
:returns: Whether the expression matches or not.
|
||||
"""
|
||||
ret: bool = eval(self.code, {"__builtins__": {}}, MatcherAdapter(matcher))
|
||||
ret: bool = eval(self.code, {'__builtins__': {}}, MatcherAdapter(matcher))
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
# mypy: allow-untyped-defs
|
||||
from __future__ import annotations
|
||||
|
||||
import collections.abc
|
||||
import dataclasses
|
||||
import inspect
|
||||
import warnings
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Collection
|
||||
|
|
@ -21,37 +24,37 @@ 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
|
||||
from ..compat import NOTSET
|
||||
from ..compat import NotSetType
|
||||
from _pytest.config import Config
|
||||
from _pytest.deprecated import check_ispytest
|
||||
from _pytest.deprecated import MARKED_FIXTURE
|
||||
from _pytest.outcomes import fail
|
||||
from _pytest.warning_types import PytestUnknownMarkWarning
|
||||
|
||||
from .._code import getfslineno
|
||||
from ..compat import ascii_escaped
|
||||
from ..compat import NOTSET
|
||||
from ..compat import NotSetType
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..nodes import Node
|
||||
|
||||
|
||||
EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
|
||||
EMPTY_PARAMETERSET_OPTION = 'empty_parameter_set_mark'
|
||||
|
||||
|
||||
def istestfunc(func) -> bool:
|
||||
return callable(func) and getattr(func, "__name__", "<lambda>") != "<lambda>"
|
||||
return callable(func) and getattr(func, '__name__', '<lambda>') != '<lambda>'
|
||||
|
||||
|
||||
def get_empty_parameterset_mark(
|
||||
config: Config, argnames: Sequence[str], func
|
||||
) -> "MarkDecorator":
|
||||
config: Config, argnames: Sequence[str], func,
|
||||
) -> MarkDecorator:
|
||||
from ..nodes import Collector
|
||||
|
||||
fs, lineno = getfslineno(func)
|
||||
reason = "got empty parameter set %r, function %s at %s:%d" % (
|
||||
reason = 'got empty parameter set %r, function %s at %s:%d' % (
|
||||
argnames,
|
||||
func.__name__,
|
||||
fs,
|
||||
|
|
@ -59,15 +62,15 @@ def get_empty_parameterset_mark(
|
|||
)
|
||||
|
||||
requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION)
|
||||
if requested_mark in ("", None, "skip"):
|
||||
if requested_mark in ('', None, 'skip'):
|
||||
mark = MARK_GEN.skip(reason=reason)
|
||||
elif requested_mark == "xfail":
|
||||
elif requested_mark == 'xfail':
|
||||
mark = MARK_GEN.xfail(reason=reason, run=False)
|
||||
elif requested_mark == "fail_at_collect":
|
||||
elif requested_mark == 'fail_at_collect':
|
||||
f_name = func.__name__
|
||||
_, lineno = getfslineno(func)
|
||||
raise Collector.CollectError(
|
||||
"Empty parameter set in '%s' at line %d" % (f_name, lineno + 1)
|
||||
"Empty parameter set in '%s' at line %d" % (f_name, lineno + 1),
|
||||
)
|
||||
else:
|
||||
raise LookupError(requested_mark)
|
||||
|
|
@ -75,17 +78,17 @@ def get_empty_parameterset_mark(
|
|||
|
||||
|
||||
class ParameterSet(NamedTuple):
|
||||
values: Sequence[Union[object, NotSetType]]
|
||||
marks: Collection[Union["MarkDecorator", "Mark"]]
|
||||
id: Optional[str]
|
||||
values: Sequence[object | NotSetType]
|
||||
marks: Collection[MarkDecorator | Mark]
|
||||
id: str | None
|
||||
|
||||
@classmethod
|
||||
def param(
|
||||
cls,
|
||||
*values: object,
|
||||
marks: Union["MarkDecorator", Collection[Union["MarkDecorator", "Mark"]]] = (),
|
||||
id: Optional[str] = None,
|
||||
) -> "ParameterSet":
|
||||
marks: MarkDecorator | Collection[MarkDecorator | Mark] = (),
|
||||
id: str | None = None,
|
||||
) -> ParameterSet:
|
||||
if isinstance(marks, MarkDecorator):
|
||||
marks = (marks,)
|
||||
else:
|
||||
|
|
@ -93,16 +96,16 @@ class ParameterSet(NamedTuple):
|
|||
|
||||
if id is not None:
|
||||
if not isinstance(id, str):
|
||||
raise TypeError(f"Expected id to be a string, got {type(id)}: {id!r}")
|
||||
raise TypeError(f'Expected id to be a string, got {type(id)}: {id!r}')
|
||||
id = ascii_escaped(id)
|
||||
return cls(values, marks, id)
|
||||
|
||||
@classmethod
|
||||
def extract_from(
|
||||
cls,
|
||||
parameterset: Union["ParameterSet", Sequence[object], object],
|
||||
parameterset: ParameterSet | Sequence[object] | object,
|
||||
force_tuple: bool = False,
|
||||
) -> "ParameterSet":
|
||||
) -> ParameterSet:
|
||||
"""Extract from an object or objects.
|
||||
|
||||
:param parameterset:
|
||||
|
|
@ -127,13 +130,13 @@ class ParameterSet(NamedTuple):
|
|||
|
||||
@staticmethod
|
||||
def _parse_parametrize_args(
|
||||
argnames: Union[str, Sequence[str]],
|
||||
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
|
||||
argnames: str | Sequence[str],
|
||||
argvalues: Iterable[ParameterSet | Sequence[object] | object],
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> Tuple[Sequence[str], bool]:
|
||||
) -> tuple[Sequence[str], bool]:
|
||||
if isinstance(argnames, str):
|
||||
argnames = [x.strip() for x in argnames.split(",") if x.strip()]
|
||||
argnames = [x.strip() for x in argnames.split(',') if x.strip()]
|
||||
force_tuple = len(argnames) == 1
|
||||
else:
|
||||
force_tuple = False
|
||||
|
|
@ -141,9 +144,9 @@ class ParameterSet(NamedTuple):
|
|||
|
||||
@staticmethod
|
||||
def _parse_parametrize_parameters(
|
||||
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
|
||||
argvalues: Iterable[ParameterSet | Sequence[object] | object],
|
||||
force_tuple: bool,
|
||||
) -> List["ParameterSet"]:
|
||||
) -> list[ParameterSet]:
|
||||
return [
|
||||
ParameterSet.extract_from(x, force_tuple=force_tuple) for x in argvalues
|
||||
]
|
||||
|
|
@ -151,12 +154,12 @@ class ParameterSet(NamedTuple):
|
|||
@classmethod
|
||||
def _for_parametrize(
|
||||
cls,
|
||||
argnames: Union[str, Sequence[str]],
|
||||
argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
|
||||
argnames: str | Sequence[str],
|
||||
argvalues: Iterable[ParameterSet | Sequence[object] | object],
|
||||
func,
|
||||
config: Config,
|
||||
nodeid: str,
|
||||
) -> Tuple[Sequence[str], List["ParameterSet"]]:
|
||||
) -> tuple[Sequence[str], list[ParameterSet]]:
|
||||
argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues)
|
||||
parameters = cls._parse_parametrize_parameters(argvalues, force_tuple)
|
||||
del argvalues
|
||||
|
|
@ -167,9 +170,9 @@ class ParameterSet(NamedTuple):
|
|||
if len(param.values) != len(argnames):
|
||||
msg = (
|
||||
'{nodeid}: in "parametrize" the number of names ({names_len}):\n'
|
||||
" {names}\n"
|
||||
"must be equal to the number of values ({values_len}):\n"
|
||||
" {values}"
|
||||
' {names}\n'
|
||||
'must be equal to the number of values ({values_len}):\n'
|
||||
' {values}'
|
||||
)
|
||||
fail(
|
||||
msg.format(
|
||||
|
|
@ -186,7 +189,7 @@ class ParameterSet(NamedTuple):
|
|||
# parameter set with NOTSET values, with the "empty parameter set" mark applied to it.
|
||||
mark = get_empty_parameterset_mark(config, argnames, func)
|
||||
parameters.append(
|
||||
ParameterSet(values=(NOTSET,) * len(argnames), marks=[mark], id=None)
|
||||
ParameterSet(values=(NOTSET,) * len(argnames), marks=[mark], id=None),
|
||||
)
|
||||
return argnames, parameters
|
||||
|
||||
|
|
@ -199,40 +202,40 @@ class Mark:
|
|||
#: Name of the mark.
|
||||
name: str
|
||||
#: Positional arguments of the mark decorator.
|
||||
args: Tuple[Any, ...]
|
||||
args: tuple[Any, ...]
|
||||
#: Keyword arguments of the mark decorator.
|
||||
kwargs: Mapping[str, Any]
|
||||
|
||||
#: Source Mark for ids with parametrize Marks.
|
||||
_param_ids_from: Optional["Mark"] = dataclasses.field(default=None, repr=False)
|
||||
_param_ids_from: Mark | None = dataclasses.field(default=None, repr=False)
|
||||
#: Resolved/generated ids with parametrize Marks.
|
||||
_param_ids_generated: Optional[Sequence[str]] = dataclasses.field(
|
||||
default=None, repr=False
|
||||
_param_ids_generated: Sequence[str] | None = dataclasses.field(
|
||||
default=None, repr=False,
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
args: Tuple[Any, ...],
|
||||
args: tuple[Any, ...],
|
||||
kwargs: Mapping[str, Any],
|
||||
param_ids_from: Optional["Mark"] = None,
|
||||
param_ids_generated: Optional[Sequence[str]] = None,
|
||||
param_ids_from: Mark | None = None,
|
||||
param_ids_generated: Sequence[str] | None = None,
|
||||
*,
|
||||
_ispytest: bool = False,
|
||||
) -> None:
|
||||
""":meta private:"""
|
||||
check_ispytest(_ispytest)
|
||||
# Weirdness to bypass frozen=True.
|
||||
object.__setattr__(self, "name", name)
|
||||
object.__setattr__(self, "args", args)
|
||||
object.__setattr__(self, "kwargs", kwargs)
|
||||
object.__setattr__(self, "_param_ids_from", param_ids_from)
|
||||
object.__setattr__(self, "_param_ids_generated", param_ids_generated)
|
||||
object.__setattr__(self, 'name', name)
|
||||
object.__setattr__(self, 'args', args)
|
||||
object.__setattr__(self, 'kwargs', kwargs)
|
||||
object.__setattr__(self, '_param_ids_from', param_ids_from)
|
||||
object.__setattr__(self, '_param_ids_generated', param_ids_generated)
|
||||
|
||||
def _has_param_ids(self) -> bool:
|
||||
return "ids" in self.kwargs or len(self.args) >= 4
|
||||
return 'ids' in self.kwargs or len(self.args) >= 4
|
||||
|
||||
def combined_with(self, other: "Mark") -> "Mark":
|
||||
def combined_with(self, other: Mark) -> Mark:
|
||||
"""Return a new Mark which is a combination of this
|
||||
Mark and another Mark.
|
||||
|
||||
|
|
@ -244,8 +247,8 @@ class Mark:
|
|||
assert self.name == other.name
|
||||
|
||||
# Remember source of ids with parametrize Marks.
|
||||
param_ids_from: Optional[Mark] = None
|
||||
if self.name == "parametrize":
|
||||
param_ids_from: Mark | None = None
|
||||
if self.name == 'parametrize':
|
||||
if other._has_param_ids():
|
||||
param_ids_from = other
|
||||
elif self._has_param_ids():
|
||||
|
|
@ -263,7 +266,7 @@ class Mark:
|
|||
# A generic parameter designating an object to which a Mark may
|
||||
# be applied -- a test function (callable) or class.
|
||||
# Note: a lambda is not allowed, but this can't be represented.
|
||||
Markable = TypeVar("Markable", bound=Union[Callable[..., object], type])
|
||||
Markable = TypeVar('Markable', bound=Union[Callable[..., object], type])
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
|
|
@ -315,7 +318,7 @@ class MarkDecorator:
|
|||
return self.mark.name
|
||||
|
||||
@property
|
||||
def args(self) -> Tuple[Any, ...]:
|
||||
def args(self) -> tuple[Any, ...]:
|
||||
"""Alias for mark.args."""
|
||||
return self.mark.args
|
||||
|
||||
|
|
@ -329,7 +332,7 @@ class MarkDecorator:
|
|||
""":meta private:"""
|
||||
return self.name # for backward-compat (2.4.1 had this attr)
|
||||
|
||||
def with_args(self, *args: object, **kwargs: object) -> "MarkDecorator":
|
||||
def with_args(self, *args: object, **kwargs: object) -> MarkDecorator:
|
||||
"""Return a MarkDecorator with extra arguments added.
|
||||
|
||||
Unlike calling the MarkDecorator, with_args() can be used even
|
||||
|
|
@ -346,7 +349,7 @@ class MarkDecorator:
|
|||
pass
|
||||
|
||||
@overload
|
||||
def __call__(self, *args: object, **kwargs: object) -> "MarkDecorator":
|
||||
def __call__(self, *args: object, **kwargs: object) -> MarkDecorator:
|
||||
pass
|
||||
|
||||
def __call__(self, *args: object, **kwargs: object):
|
||||
|
|
@ -361,10 +364,10 @@ class MarkDecorator:
|
|||
|
||||
|
||||
def get_unpacked_marks(
|
||||
obj: Union[object, type],
|
||||
obj: object | type,
|
||||
*,
|
||||
consider_mro: bool = True,
|
||||
) -> List[Mark]:
|
||||
) -> list[Mark]:
|
||||
"""Obtain the unpacked marks that are stored on an object.
|
||||
|
||||
If obj is a class and consider_mro is true, return marks applied to
|
||||
|
|
@ -373,10 +376,10 @@ def get_unpacked_marks(
|
|||
"""
|
||||
if isinstance(obj, type):
|
||||
if not consider_mro:
|
||||
mark_lists = [obj.__dict__.get("pytestmark", [])]
|
||||
mark_lists = [obj.__dict__.get('pytestmark', [])]
|
||||
else:
|
||||
mark_lists = [
|
||||
x.__dict__.get("pytestmark", []) for x in reversed(obj.__mro__)
|
||||
x.__dict__.get('pytestmark', []) for x in reversed(obj.__mro__)
|
||||
]
|
||||
mark_list = []
|
||||
for item in mark_lists:
|
||||
|
|
@ -385,7 +388,7 @@ def get_unpacked_marks(
|
|||
else:
|
||||
mark_list.append(item)
|
||||
else:
|
||||
mark_attribute = getattr(obj, "pytestmark", [])
|
||||
mark_attribute = getattr(obj, 'pytestmark', [])
|
||||
if isinstance(mark_attribute, list):
|
||||
mark_list = mark_attribute
|
||||
else:
|
||||
|
|
@ -394,7 +397,7 @@ def get_unpacked_marks(
|
|||
|
||||
|
||||
def normalize_mark_list(
|
||||
mark_list: Iterable[Union[Mark, MarkDecorator]],
|
||||
mark_list: Iterable[Mark | MarkDecorator],
|
||||
) -> Iterable[Mark]:
|
||||
"""
|
||||
Normalize an iterable of Mark or MarkDecorator objects into a list of marks
|
||||
|
|
@ -404,9 +407,9 @@ def normalize_mark_list(
|
|||
:returns: A new list of the extracted Mark objects
|
||||
"""
|
||||
for mark in mark_list:
|
||||
mark_obj = getattr(mark, "mark", mark)
|
||||
mark_obj = getattr(mark, 'mark', mark)
|
||||
if not isinstance(mark_obj, Mark):
|
||||
raise TypeError(f"got {mark_obj!r} instead of Mark")
|
||||
raise TypeError(f'got {mark_obj!r} instead of Mark')
|
||||
yield mark_obj
|
||||
|
||||
|
||||
|
|
@ -438,14 +441,14 @@ if TYPE_CHECKING:
|
|||
...
|
||||
|
||||
@overload
|
||||
def __call__(self, reason: str = ...) -> "MarkDecorator":
|
||||
def __call__(self, reason: str = ...) -> MarkDecorator:
|
||||
...
|
||||
|
||||
class _SkipifMarkDecorator(MarkDecorator):
|
||||
def __call__( # type: ignore[override]
|
||||
self,
|
||||
condition: Union[str, bool] = ...,
|
||||
*conditions: Union[str, bool],
|
||||
condition: str | bool = ...,
|
||||
*conditions: str | bool,
|
||||
reason: str = ...,
|
||||
) -> MarkDecorator:
|
||||
...
|
||||
|
|
@ -458,13 +461,13 @@ if TYPE_CHECKING:
|
|||
@overload
|
||||
def __call__(
|
||||
self,
|
||||
condition: Union[str, bool] = False,
|
||||
*conditions: Union[str, bool],
|
||||
condition: str | bool = False,
|
||||
*conditions: str | bool,
|
||||
reason: str = ...,
|
||||
run: bool = ...,
|
||||
raises: Union[
|
||||
None, Type[BaseException], Tuple[Type[BaseException], ...]
|
||||
] = ...,
|
||||
raises: (
|
||||
None | type[BaseException] | tuple[type[BaseException], ...]
|
||||
) = ...,
|
||||
strict: bool = ...,
|
||||
) -> MarkDecorator:
|
||||
...
|
||||
|
|
@ -472,17 +475,15 @@ if TYPE_CHECKING:
|
|||
class _ParametrizeMarkDecorator(MarkDecorator):
|
||||
def __call__( # type: ignore[override]
|
||||
self,
|
||||
argnames: Union[str, Sequence[str]],
|
||||
argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
|
||||
argnames: str | Sequence[str],
|
||||
argvalues: Iterable[ParameterSet | Sequence[object] | object],
|
||||
*,
|
||||
indirect: Union[bool, Sequence[str]] = ...,
|
||||
ids: Optional[
|
||||
Union[
|
||||
Iterable[Union[None, str, float, int, bool]],
|
||||
Callable[[Any], Optional[object]],
|
||||
]
|
||||
] = ...,
|
||||
scope: Optional[_ScopeName] = ...,
|
||||
indirect: bool | Sequence[str] = ...,
|
||||
ids: None | (
|
||||
Iterable[None | str | float | int | bool] |
|
||||
Callable[[Any], object | None]
|
||||
) = ...,
|
||||
scope: _ScopeName | None = ...,
|
||||
) -> MarkDecorator:
|
||||
...
|
||||
|
||||
|
|
@ -523,24 +524,24 @@ class MarkGenerator:
|
|||
|
||||
def __init__(self, *, _ispytest: bool = False) -> None:
|
||||
check_ispytest(_ispytest)
|
||||
self._config: Optional[Config] = None
|
||||
self._markers: Set[str] = set()
|
||||
self._config: Config | None = None
|
||||
self._markers: set[str] = set()
|
||||
|
||||
def __getattr__(self, name: str) -> MarkDecorator:
|
||||
"""Generate a new :class:`MarkDecorator` with the given name."""
|
||||
if name[0] == "_":
|
||||
raise AttributeError("Marker name must NOT start with underscore")
|
||||
if name[0] == '_':
|
||||
raise AttributeError('Marker name must NOT start with underscore')
|
||||
|
||||
if self._config is not None:
|
||||
# We store a set of markers as a performance optimisation - if a mark
|
||||
# name is in the set we definitely know it, but a mark may be known and
|
||||
# not in the set. We therefore start by updating the set!
|
||||
if name not in self._markers:
|
||||
for line in self._config.getini("markers"):
|
||||
for line in self._config.getini('markers'):
|
||||
# example lines: "skipif(condition): skip the given test if..."
|
||||
# or "hypothesis: tests which use Hypothesis", so to get the
|
||||
# marker name we split on both `:` and `(`.
|
||||
marker = line.split(":")[0].split("(")[0].strip()
|
||||
marker = line.split(':')[0].split('(')[0].strip()
|
||||
self._markers.add(marker)
|
||||
|
||||
# If the name is not in the set of known marks after updating,
|
||||
|
|
@ -548,19 +549,19 @@ class MarkGenerator:
|
|||
if name not in self._markers:
|
||||
if self._config.option.strict_markers or self._config.option.strict:
|
||||
fail(
|
||||
f"{name!r} not found in `markers` configuration option",
|
||||
f'{name!r} not found in `markers` configuration option',
|
||||
pytrace=False,
|
||||
)
|
||||
|
||||
# Raise a specific error for common misspellings of "parametrize".
|
||||
if name in ["parameterize", "parametrise", "parameterise"]:
|
||||
if name in ['parameterize', 'parametrise', 'parameterise']:
|
||||
__tracebackhide__ = True
|
||||
fail(f"Unknown '{name}' mark, did you mean 'parametrize'?")
|
||||
|
||||
warnings.warn(
|
||||
"Unknown pytest.mark.%s - is this a typo? You can register "
|
||||
"custom marks to avoid this warning - for details, see "
|
||||
"https://docs.pytest.org/en/stable/how-to/mark.html" % name,
|
||||
'Unknown pytest.mark.%s - is this a typo? You can register '
|
||||
'custom marks to avoid this warning - for details, see '
|
||||
'https://docs.pytest.org/en/stable/how-to/mark.html' % name,
|
||||
PytestUnknownMarkWarning,
|
||||
2,
|
||||
)
|
||||
|
|
@ -573,9 +574,9 @@ MARK_GEN = MarkGenerator(_ispytest=True)
|
|||
|
||||
@final
|
||||
class NodeKeywords(MutableMapping[str, Any]):
|
||||
__slots__ = ("node", "parent", "_markers")
|
||||
__slots__ = ('node', 'parent', '_markers')
|
||||
|
||||
def __init__(self, node: "Node") -> None:
|
||||
def __init__(self, node: Node) -> None:
|
||||
self.node = node
|
||||
self.parent = node.parent
|
||||
self._markers = {node.name: True}
|
||||
|
|
@ -596,21 +597,21 @@ class NodeKeywords(MutableMapping[str, Any]):
|
|||
|
||||
def __contains__(self, key: object) -> bool:
|
||||
return (
|
||||
key in self._markers
|
||||
or self.parent is not None
|
||||
and key in self.parent.keywords
|
||||
key in self._markers or
|
||||
self.parent is not None and
|
||||
key in self.parent.keywords
|
||||
)
|
||||
|
||||
def update( # type: ignore[override]
|
||||
self,
|
||||
other: Union[Mapping[str, Any], Iterable[Tuple[str, Any]]] = (),
|
||||
other: Mapping[str, Any] | Iterable[tuple[str, Any]] = (),
|
||||
**kwds: Any,
|
||||
) -> None:
|
||||
self._markers.update(other)
|
||||
self._markers.update(kwds)
|
||||
|
||||
def __delitem__(self, key: str) -> None:
|
||||
raise ValueError("cannot delete key in keywords dict")
|
||||
raise ValueError('cannot delete key in keywords dict')
|
||||
|
||||
def __iter__(self) -> Iterator[str]:
|
||||
# Doesn't need to be fast.
|
||||
|
|
@ -626,4 +627,4 @@ class NodeKeywords(MutableMapping[str, Any]):
|
|||
return sum(1 for keyword in self)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<NodeKeywords for node {self.node}>"
|
||||
return f'<NodeKeywords for node {self.node}>'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue