From 4354bae714a5e043fd286d7004878cd163babf26 Mon Sep 17 00:00:00 2001 From: Virendra Patil Date: Mon, 24 Jun 2024 02:26:13 +0530 Subject: [PATCH] Fixed handling of invalid regex pattern --- src/_pytest/python_api.py | 44 +++++++++++++++++++++------------------ testing/python/raises.py | 21 +++++++++++++++++++ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index c1e851391..536942327 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -1,31 +1,32 @@ # mypy: allow-untyped-defs from __future__ import annotations -from collections.abc import Collection -from collections.abc import Sized -from decimal import Decimal import math -from numbers import Complex import pprint +import re +from collections.abc import Collection, Sized +from decimal import Decimal +from numbers import Complex from types import TracebackType -from typing import Any -from typing import Callable -from typing import cast -from typing import ContextManager -from typing import final -from typing import Mapping -from typing import overload -from typing import Pattern -from typing import Sequence -from typing import Tuple -from typing import Type -from typing import TYPE_CHECKING -from typing import TypeVar +from typing import ( + TYPE_CHECKING, + Any, + Callable, + ContextManager, + Mapping, + Pattern, + Sequence, + Tuple, + Type, + TypeVar, + cast, + final, + overload, +) import _pytest._code from _pytest.outcomes import fail - if TYPE_CHECKING: from numpy import ndarray @@ -1006,6 +1007,9 @@ class RaisesContext(ContextManager[_pytest._code.ExceptionInfo[E]]): # Cast to narrow the exception type now that it's verified. exc_info = cast(Tuple[Type[E], E, TracebackType], (exc_type, exc_val, exc_tb)) self.excinfo.fill_unfilled(exc_info) - if self.match_expr is not None: - self.excinfo.match(self.match_expr) + try: + if self.match_expr: + self.excinfo.match(self.match_expr) + except re.error as e: + fail(f"Invalid regex pattern provided to 'match': {e}") return True diff --git a/testing/python/raises.py b/testing/python/raises.py index 271dd3e5a..d435ea9d1 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -6,6 +6,7 @@ import sys from _pytest.outcomes import Failed from _pytest.pytester import Pytester + import pytest @@ -132,6 +133,26 @@ class TestRaises: result = pytester.runpytest() result.stdout.fnmatch_lines(["*2 failed*"]) + def test_raises_with_invalid_regex(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + def test_invalid_regex(): + with pytest.raises(ValueError, match="invalid regex character ["): + raise ValueError() + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*Invalid regex pattern provided to 'match': unterminated character set at position 24*", + ] + ) + result.stdout.no_fnmatch_line("*Traceback*") + result.stdout.no_fnmatch_line("*File*") + result.stdout.no_fnmatch_line("*line*") + def test_noclass(self) -> None: with pytest.raises(TypeError): pytest.raises("wrong", lambda: None) # type: ignore[call-overload]