Skip to content

Commit 1613a12

Browse files
bysiberbluetech
authored andcommitted
raises: fix regex escaping warning not considering | as needs escaping
The pipe character is a regex metacharacter (alternation operator) but is_fully_escaped did not include it, so a match pattern like '^foo|bar$' would be wrongly identified as a fully-escaped literal. This causes rawmatch to be set incorrectly, leading to misleading diff output on match failure. Also add | to the unescape function's character class for consistency.
1 parent 12558b5 commit 1613a12

3 files changed

Lines changed: 12 additions & 2 deletions

File tree

changelog/13192.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed `|` (pipe) not being treated as a regex meta-character that needs escaping in :func:`pytest.raises(match=...) <pytest.raises>`.

src/_pytest/raises.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,14 +363,14 @@ def _check_raw_type(
363363

364364
def is_fully_escaped(s: str) -> bool:
365365
# we know we won't compile with re.VERBOSE, so whitespace doesn't need to be escaped
366-
metacharacters = "{}()+.*?^$[]"
366+
metacharacters = "{}()+.*?^$[]|"
367367
return not any(
368368
c in metacharacters and (i == 0 or s[i - 1] != "\\") for (i, c) in enumerate(s)
369369
)
370370

371371

372372
def unescape(s: str) -> str:
373-
return re.sub(r"\\([{}()+-.*?^$\[\]\s\\])", r"\1", s)
373+
return re.sub(r"\\([{}()+-.*?^$\[\]\s\\|])", r"\1", s)
374374

375375

376376
# These classes conceptually differ from ExceptionInfo in that ExceptionInfo is tied, and

testing/python/raises.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,12 @@ def test_raises_match_compiled_regex(self) -> None:
430430
pattern_with_flags = re.compile(r"INVALID LITERAL", re.IGNORECASE)
431431
with pytest.raises(ValueError, match=pattern_with_flags):
432432
int("asdf")
433+
434+
def test_pipe_is_treated_as_regex_metacharacter(self) -> None:
435+
"""| (pipe) must be recognized as a regex metacharacter."""
436+
from _pytest.raises import is_fully_escaped
437+
from _pytest.raises import unescape
438+
439+
assert not is_fully_escaped("foo|bar")
440+
assert is_fully_escaped(r"foo\|bar")
441+
assert unescape(r"foo\|bar") == "foo|bar"

0 commit comments

Comments
 (0)