Merge 54beed5df7
into 63dfa4bb84
This commit is contained in:
commit
f91f6f470c
1
AUTHORS
1
AUTHORS
|
@ -271,6 +271,7 @@ Matt Bachmann
|
||||||
Matt Duck
|
Matt Duck
|
||||||
Matt Williams
|
Matt Williams
|
||||||
Matthias Hafner
|
Matthias Hafner
|
||||||
|
Max Berkowitz
|
||||||
Maxim Filipenko
|
Maxim Filipenko
|
||||||
Maximilian Cosmo Sitter
|
Maximilian Cosmo Sitter
|
||||||
mbyt
|
mbyt
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Emit a warning when unregistered marks are used with the command line option -m.
|
|
@ -236,7 +236,7 @@ def deselect_by_mark(items: "List[Item]", config: Config) -> None:
|
||||||
if not matchexpr:
|
if not matchexpr:
|
||||||
return
|
return
|
||||||
|
|
||||||
expr = _parse_expression(matchexpr, "Wrong expression passed to '-m'")
|
expr = _parse_expression(matchexpr, "Wrong expression passed to '-m'", True)
|
||||||
remaining: List[Item] = []
|
remaining: List[Item] = []
|
||||||
deselected: List[Item] = []
|
deselected: List[Item] = []
|
||||||
for item in items:
|
for item in items:
|
||||||
|
@ -249,9 +249,9 @@ def deselect_by_mark(items: "List[Item]", config: Config) -> None:
|
||||||
items[:] = remaining
|
items[:] = remaining
|
||||||
|
|
||||||
|
|
||||||
def _parse_expression(expr: str, exc_message: str) -> Expression:
|
def _parse_expression(expr: str, exc_message: str, mark: bool = False) -> Expression:
|
||||||
try:
|
try:
|
||||||
return Expression.compile(expr)
|
return Expression.compile(expr, mark)
|
||||||
except ParseError as e:
|
except ParseError as e:
|
||||||
raise UsageError(f"{exc_message}: {expr}: {e}") from None
|
raise UsageError(f"{exc_message}: {expr}: {e}") from None
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ from typing import NoReturn
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
|
||||||
|
from .structures import MARK_GEN
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Expression",
|
"Expression",
|
||||||
|
@ -197,12 +199,19 @@ class Expression:
|
||||||
self.code = code
|
self.code = code
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def compile(self, input: str) -> "Expression":
|
def compile(self, input: str, mark: bool = False) -> "Expression":
|
||||||
"""Compile a match expression.
|
"""Compile a match expression.
|
||||||
|
|
||||||
:param input: The input expression - one line.
|
:param input: The input expression - one line.
|
||||||
"""
|
"""
|
||||||
astexpr = expression(Scanner(input))
|
astexpr = expression(Scanner(input))
|
||||||
|
|
||||||
|
if mark:
|
||||||
|
for node in ast.walk(astexpr):
|
||||||
|
# if the node is an identifier, i.e. a mark name
|
||||||
|
if isinstance(node, ast.Name):
|
||||||
|
MARK_GEN.verify_mark(node.id[len(IDENT_PREFIX) :])
|
||||||
|
|
||||||
code: types.CodeType = compile(
|
code: types.CodeType = compile(
|
||||||
astexpr,
|
astexpr,
|
||||||
filename="<pytest match expression>",
|
filename="<pytest match expression>",
|
||||||
|
|
|
@ -520,11 +520,7 @@ class MarkGenerator:
|
||||||
self._config: Optional[Config] = None
|
self._config: Optional[Config] = None
|
||||||
self._markers: Set[str] = set()
|
self._markers: Set[str] = set()
|
||||||
|
|
||||||
def __getattr__(self, name: str) -> MarkDecorator:
|
def verify_mark(self, name: str) -> None:
|
||||||
"""Generate a new :class:`MarkDecorator` with the given name."""
|
|
||||||
if name[0] == "_":
|
|
||||||
raise AttributeError("Marker name must NOT start with underscore")
|
|
||||||
|
|
||||||
if self._config is not None:
|
if self._config is not None:
|
||||||
# We store a set of markers as a performance optimisation - if a mark
|
# 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
|
# name is in the set we definitely know it, but a mark may be known and
|
||||||
|
@ -556,9 +552,16 @@ class MarkGenerator:
|
||||||
"custom marks to avoid this warning - for details, see "
|
"custom marks to avoid this warning - for details, see "
|
||||||
"https://docs.pytest.org/en/stable/how-to/mark.html",
|
"https://docs.pytest.org/en/stable/how-to/mark.html",
|
||||||
PytestUnknownMarkWarning,
|
PytestUnknownMarkWarning,
|
||||||
2,
|
3,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
self.verify_mark(name)
|
||||||
|
|
||||||
return MarkDecorator(Mark(name, (), {}, _ispytest=True), _ispytest=True)
|
return MarkDecorator(Mark(name, (), {}, _ispytest=True), _ispytest=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue