Was testing -k with a test name that contains backslash-escaped characters (like the \n you get from parametrized test IDs) alongside a marker expression with string arguments, and ran into a false rejection.
The scanner in src/_pytest/mark/expression.py line 105:
if (backslash_pos := input.find("\\")) != -1:
raise SyntaxError(
r'escaping with "\\" not supported in marker expression',
(FILE_NAME, 1, backslash_pos + 1, input),
)
This searches the entire input for a backslash, but it should only search within the current string literal (value). The original code before commit 1e7eb20 used "\\" in value which was correct. The refactoring to input.find("\\") accidentally changed the search scope.
This means any expression that has a backslash in an identifier (which is valid per #8983) AND also contains a string literal will be incorrectly rejected:
$ pytest -k 'test\nfoo\n and mark(x="y")'
ERROR: Wrong expression passed to '-k': test\nfoo\n and mark(x="y"): at column 5: escaping with "\" not supported in marker expression
The backslash at position 4 is in the identifier test\nfoo\n, not inside the string literal "y". But input.find("\\") finds it anyway because it scans the whole input.
Repro:
from _pytest.mark.expression import Expression
# Works fine -- backslash in identifier, no string literal
Expression.compile(r'test\nfoo\n') # ok
# Works fine -- backslash inside string literal, correctly rejected
try:
Expression.compile(r"mark(var='\hello')")
except SyntaxError:
pass # expected
# Broken -- backslash in identifier + string literal = false rejection
Expression.compile(r'test\nfoo\n and mark(x="y")') # SyntaxError!
The fix is changing input.find("\\") to value.find("\\") and adjusting the column offset from backslash_pos + 1 to pos + backslash_pos + 1 so the error points to the right place when a backslash actually is inside a string.
This is a regression from #8983 -- that fix made backslashes valid in identifiers, but this bug means they still cause errors when a string literal happens to appear anywhere in the same expression.
Was testing
-kwith a test name that contains backslash-escaped characters (like the\nyou get from parametrized test IDs) alongside a marker expression with string arguments, and ran into a false rejection.The scanner in
src/_pytest/mark/expression.pyline 105:This searches the entire input for a backslash, but it should only search within the current string literal (
value). The original code before commit 1e7eb20 used"\\" in valuewhich was correct. The refactoring toinput.find("\\")accidentally changed the search scope.This means any expression that has a backslash in an identifier (which is valid per #8983) AND also contains a string literal will be incorrectly rejected:
The backslash at position 4 is in the identifier
test\nfoo\n, not inside the string literal"y". Butinput.find("\\")finds it anyway because it scans the whole input.Repro:
The fix is changing
input.find("\\")tovalue.find("\\")and adjusting the column offset frombackslash_pos + 1topos + backslash_pos + 1so the error points to the right place when a backslash actually is inside a string.This is a regression from #8983 -- that fix made backslashes valid in identifiers, but this bug means they still cause errors when a string literal happens to appear anywhere in the same expression.