Skip to content

Commit d18e14c

Browse files
committed
Don't remove, just deprecate assert_raises_regex
1 parent da8ab9b commit d18e14c

File tree

2 files changed

+142
-1
lines changed

2 files changed

+142
-1
lines changed

pandas/tests/util/test_testing.py

+10
Original file line numberDiff line numberDiff line change
@@ -884,3 +884,13 @@ def test_create_temp_directory():
884884
assert os.path.exists(path)
885885
assert os.path.isdir(path)
886886
assert not os.path.exists(path)
887+
888+
889+
def test_assert_raises_regex_deprecated():
890+
# see gh-23592
891+
892+
with tm.assert_produces_warning(FutureWarning):
893+
msg = "Not equal!"
894+
895+
with tm.assert_raises_regex(AssertionError, msg):
896+
assert 1 == 2, msg

pandas/util/testing.py

+132-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import pandas.compat as compat
2222
from pandas.compat import (
2323
PY2, PY3, Counter, StringIO, callable, filter, httplib, lmap, lrange, lzip,
24-
map, range, string_types, u, unichr, zip)
24+
map, raise_with_traceback, range, string_types, u, unichr, zip)
2525

2626
from pandas.core.dtypes.common import (
2727
is_bool, is_categorical_dtype, is_datetimelike_v_numeric,
@@ -2532,6 +2532,137 @@ def wrapper(*args, **kwargs):
25322532
with_connectivity_check = network
25332533

25342534

2535+
def assert_raises_regex(_exception, _regexp, _callable=None,
2536+
*args, **kwargs):
2537+
r"""
2538+
Check that the specified Exception is raised and that the error message
2539+
matches a given regular expression pattern. This may be a regular
2540+
expression object or a string containing a regular expression suitable
2541+
for use by `re.search()`. This is a port of the `assertRaisesRegexp`
2542+
function from unittest in Python 2.7.
2543+
2544+
.. deprecated:: 0.24.0
2545+
Use `pytest.raises` instead.
2546+
2547+
Examples
2548+
--------
2549+
>>> assert_raises_regex(ValueError, 'invalid literal for.*XYZ', int, 'XYZ')
2550+
>>> import re
2551+
>>> assert_raises_regex(ValueError, re.compile('literal'), int, 'XYZ')
2552+
2553+
If an exception of a different type is raised, it bubbles up.
2554+
2555+
>>> assert_raises_regex(TypeError, 'literal', int, 'XYZ')
2556+
Traceback (most recent call last):
2557+
...
2558+
ValueError: invalid literal for int() with base 10: 'XYZ'
2559+
>>> dct = dict()
2560+
>>> assert_raises_regex(KeyError, 'pear', dct.__getitem__, 'apple')
2561+
Traceback (most recent call last):
2562+
...
2563+
AssertionError: "pear" does not match "'apple'"
2564+
2565+
You can also use this in a with statement.
2566+
2567+
>>> with assert_raises_regex(TypeError, r'unsupported operand type\(s\)'):
2568+
... 1 + {}
2569+
>>> with assert_raises_regex(TypeError, 'banana'):
2570+
... 'apple'[0] = 'b'
2571+
Traceback (most recent call last):
2572+
...
2573+
AssertionError: "banana" does not match "'str' object does not support \
2574+
item assignment"
2575+
"""
2576+
warnings.warn(("assert_raises_regex has been deprecated and will "
2577+
"be removed in the next release. Please use "
2578+
"`pytest.raises` instead."), FutureWarning, stacklevel=2)
2579+
2580+
manager = _AssertRaisesContextmanager(exception=_exception, regexp=_regexp)
2581+
if _callable is not None:
2582+
with manager:
2583+
_callable(*args, **kwargs)
2584+
else:
2585+
return manager
2586+
2587+
2588+
class _AssertRaisesContextmanager(object):
2589+
"""
2590+
Context manager behind `assert_raises_regex`.
2591+
"""
2592+
2593+
def __init__(self, exception, regexp=None):
2594+
"""
2595+
Initialize an _AssertRaisesContextManager instance.
2596+
2597+
Parameters
2598+
----------
2599+
exception : class
2600+
The expected Exception class.
2601+
regexp : str, default None
2602+
The regex to compare against the Exception message.
2603+
"""
2604+
2605+
self.exception = exception
2606+
2607+
if regexp is not None and not hasattr(regexp, "search"):
2608+
regexp = re.compile(regexp, re.DOTALL)
2609+
2610+
self.regexp = regexp
2611+
2612+
def __enter__(self):
2613+
return self
2614+
2615+
def __exit__(self, exc_type, exc_value, trace_back):
2616+
expected = self.exception
2617+
2618+
if not exc_type:
2619+
exp_name = getattr(expected, "__name__", str(expected))
2620+
raise AssertionError("{name} not raised.".format(name=exp_name))
2621+
2622+
return self.exception_matches(exc_type, exc_value, trace_back)
2623+
2624+
def exception_matches(self, exc_type, exc_value, trace_back):
2625+
"""
2626+
Check that the Exception raised matches the expected Exception
2627+
and expected error message regular expression.
2628+
2629+
Parameters
2630+
----------
2631+
exc_type : class
2632+
The type of Exception raised.
2633+
exc_value : Exception
2634+
The instance of `exc_type` raised.
2635+
trace_back : stack trace object
2636+
The traceback object associated with `exc_value`.
2637+
2638+
Returns
2639+
-------
2640+
is_matched : bool
2641+
Whether or not the Exception raised matches the expected
2642+
Exception class and expected error message regular expression.
2643+
2644+
Raises
2645+
------
2646+
AssertionError : The error message provided does not match
2647+
the expected error message regular expression.
2648+
"""
2649+
2650+
if issubclass(exc_type, self.exception):
2651+
if self.regexp is not None:
2652+
val = str(exc_value)
2653+
2654+
if not self.regexp.search(val):
2655+
msg = '"{pat}" does not match "{val}"'.format(
2656+
pat=self.regexp.pattern, val=val)
2657+
e = AssertionError(msg)
2658+
raise_with_traceback(e, trace_back)
2659+
2660+
return True
2661+
else:
2662+
# Failed, so allow Exception to bubble up.
2663+
return False
2664+
2665+
25352666
@contextmanager
25362667
def assert_produces_warning(expected_warning=Warning, filter_level="always",
25372668
clear=None, check_stacklevel=True):

0 commit comments

Comments
 (0)