Skip to content

Commit 25c6561

Browse files
committedAug 8, 2021
mark/expression: allow backslash characters in identifiers
Fixes #8983.
1 parent a446ee8 commit 25c6561

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed
 

‎changelog/8983.bugfix.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The test selection options ``pytest -k`` and ``pytest -m`` now support matching names containing backslash (`\\`) characters.
2+
Backslashes are treated literally, not as escape characters (the values being matched against are already escaped).

‎src/_pytest/mark/expression.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
expr: and_expr ('or' and_expr)*
77
and_expr: not_expr ('and' not_expr)*
88
not_expr: 'not' not_expr | '(' expr ')' | ident
9-
ident: (\w|:|\+|-|\.|\[|\])+
9+
ident: (\w|:|\+|-|\.|\[|\]|\\)+
1010
1111
The semantics are:
1212
@@ -88,7 +88,7 @@ def lex(self, input: str) -> Iterator[Token]:
8888
yield Token(TokenType.RPAREN, ")", pos)
8989
pos += 1
9090
else:
91-
match = re.match(r"(:?\w|:|\+|-|\.|\[|\])+", input[pos:])
91+
match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\)+", input[pos:])
9292
if match:
9393
value = match.group(0)
9494
if value == "or":

‎testing/test_mark_expression.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ def test_syntax_oddeties(expr: str, expected: bool) -> None:
6666
assert evaluate(expr, matcher) is expected
6767

6868

69+
def test_backslash_not_treated_specially() -> None:
70+
r"""When generating nodeids, if the source name contains special characters
71+
like a newline, they are escaped into two characters like \n. Therefore, a
72+
user will never need to insert a literal newline, only \n (two chars). So
73+
mark expressions themselves do not support escaping, instead they treat
74+
backslashes as regular identifier characters."""
75+
matcher = {r"\nfoo\n"}.__contains__
76+
77+
assert evaluate(r"\nfoo\n", matcher)
78+
assert not evaluate(r"foo", matcher)
79+
with pytest.raises(ParseError):
80+
evaluate("\nfoo\n", matcher)
81+
82+
6983
@pytest.mark.parametrize(
7084
("expr", "column", "message"),
7185
(
@@ -129,6 +143,7 @@ def test_syntax_errors(expr: str, column: int, message: str) -> None:
129143
":::",
130144
"a:::c",
131145
"a+-b",
146+
r"\nhe\\l\lo\n\t\rbye",
132147
"אבגד",
133148
"aaאבגדcc",
134149
"a[bcd]",
@@ -156,7 +171,6 @@ def test_valid_idents(ident: str) -> None:
156171
"ident",
157172
(
158173
"/",
159-
"\\",
160174
"^",
161175
"*",
162176
"=",

0 commit comments

Comments
 (0)
Please sign in to comment.