Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/14474.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a regression where ``-k`` and ``-m`` expressions containing both backslash characters in identifiers and string literal arguments would incorrectly raise a ``SyntaxError`` about escaping.
4 changes: 2 additions & 2 deletions src/_pytest/mark/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ def lex(self, input: str) -> Iterator[Token]:
(FILE_NAME, 1, pos + 1, input),
)
value = input[pos : end_quote_pos + 1]
if (backslash_pos := input.find("\\")) != -1:
if (backslash_pos := value.find("\\")) != -1:
raise SyntaxError(
r'escaping with "\" not supported in marker expression',
(FILE_NAME, 1, backslash_pos + 1, input),
(FILE_NAME, 1, pos + backslash_pos + 1, input),
)
yield Token(TokenType.STRING, value, pos)
pos += len(value)
Expand Down
14 changes: 14 additions & 0 deletions testing/test_mark_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ def matcher(name: str, /, **kwargs: str | int | bool | None) -> bool:
evaluate("\nfoo\n", matcher)


def test_backslash_in_identifier_with_string_literal() -> None:
r"""Backslashes in identifiers should not cause false rejections when the
expression also contains string literals. Regression test for a bug where
the scanner searched the entire input for backslashes instead of only the
current string literal value."""

def matcher(name: str, /, **kwargs: str | int | bool | None) -> bool:
return {r"\nfoo\n", r"test\case", "mark"}.__contains__(name)

assert evaluate(r'\nfoo\n and mark(x="y")', matcher)
assert evaluate(r'mark(x="y") and \nfoo\n', matcher)
assert evaluate(r'test\case and mark(x="y")', matcher)


@pytest.mark.parametrize(
("expr", "column", "message"),
(
Expand Down
Loading