Skip to content

mark expression scanner: backslash check in string literal searches entire input instead of the string value #14474

Description

@EternalRights

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions