1
1
from __future__ import annotations
2
2
3
- from collections .abc import Callable
4
- from typing import cast
5
-
6
3
from _pytest .mark import MarkMatcher
7
4
from _pytest .mark .expression import Expression
8
5
from _pytest .mark .expression import MatcherCall
9
6
from _pytest .mark .expression import ParseError
10
7
import pytest
11
8
12
9
13
- def evaluate (input : str , matcher : Callable [[ str ], bool ] ) -> bool :
14
- return Expression .compile (input ).evaluate (cast ( MatcherCall , matcher ) )
10
+ def evaluate (input : str , matcher : MatcherCall ) -> bool :
11
+ return Expression .compile (input ).evaluate (matcher )
15
12
16
13
17
14
def test_empty_is_false () -> None :
18
- assert not evaluate ("" , lambda ident : False )
19
- assert not evaluate ("" , lambda ident : True )
20
- assert not evaluate (" " , lambda ident : False )
21
- assert not evaluate ("\t " , lambda ident : False )
15
+ assert not evaluate ("" , lambda ident , / , ** kwargs : False )
16
+ assert not evaluate ("" , lambda ident , / , ** kwargs : True )
17
+ assert not evaluate (" " , lambda ident , / , ** kwargs : False )
18
+ assert not evaluate ("\t " , lambda ident , / , ** kwargs : False )
22
19
23
20
24
21
@pytest .mark .parametrize (
@@ -51,7 +48,9 @@ def test_empty_is_false() -> None:
51
48
),
52
49
)
53
50
def test_basic (expr : str , expected : bool ) -> None :
54
- matcher = {"true" : True , "false" : False }.__getitem__
51
+ def matcher (name : str , / , ** kwargs : str | int | bool | None ) -> bool :
52
+ return {"true" : True , "false" : False }[name ]
53
+
55
54
assert evaluate (expr , matcher ) is expected
56
55
57
56
@@ -67,7 +66,9 @@ def test_basic(expr: str, expected: bool) -> None:
67
66
),
68
67
)
69
68
def test_syntax_oddities (expr : str , expected : bool ) -> None :
70
- matcher = {"true" : True , "false" : False }.__getitem__
69
+ def matcher (name : str , / , ** kwargs : str | int | bool | None ) -> bool :
70
+ return {"true" : True , "false" : False }[name ]
71
+
71
72
assert evaluate (expr , matcher ) is expected
72
73
73
74
@@ -77,7 +78,9 @@ def test_backslash_not_treated_specially() -> None:
77
78
user will never need to insert a literal newline, only \n (two chars). So
78
79
mark expressions themselves do not support escaping, instead they treat
79
80
backslashes as regular identifier characters."""
80
- matcher = {r"\nfoo\n" }.__contains__
81
+
82
+ def matcher (name : str , / , ** kwargs : str | int | bool | None ) -> bool :
83
+ return {r"\nfoo\n" }.__contains__ (name )
81
84
82
85
assert evaluate (r"\nfoo\n" , matcher )
83
86
assert not evaluate (r"foo" , matcher )
@@ -135,7 +138,7 @@ def test_backslash_not_treated_specially() -> None:
135
138
)
136
139
def test_syntax_errors (expr : str , column : int , message : str ) -> None :
137
140
with pytest .raises (ParseError ) as excinfo :
138
- evaluate (expr , lambda ident : True )
141
+ evaluate (expr , lambda ident , / , ** kwargs : True )
139
142
assert excinfo .value .column == column
140
143
assert excinfo .value .message == message
141
144
@@ -172,7 +175,10 @@ def test_syntax_errors(expr: str, column: int, message: str) -> None:
172
175
),
173
176
)
174
177
def test_valid_idents (ident : str ) -> None :
175
- assert evaluate (ident , {ident : True }.__getitem__ )
178
+ def matcher (name : str , / , ** kwargs : str | int | bool | None ) -> bool :
179
+ return name == ident
180
+
181
+ assert evaluate (ident , matcher )
176
182
177
183
178
184
@pytest .mark .parametrize (
@@ -199,7 +205,7 @@ def test_valid_idents(ident: str) -> None:
199
205
)
200
206
def test_invalid_idents (ident : str ) -> None :
201
207
with pytest .raises (ParseError ):
202
- evaluate (ident , lambda ident : True )
208
+ evaluate (ident , lambda ident , / , ** kwargs : True )
203
209
204
210
205
211
@pytest .mark .parametrize (
0 commit comments