|
21 | 21 | import pandas.compat as compat
|
22 | 22 | from pandas.compat import (
|
23 | 23 | 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) |
25 | 25 |
|
26 | 26 | from pandas.core.dtypes.common import (
|
27 | 27 | is_bool, is_categorical_dtype, is_datetimelike_v_numeric,
|
@@ -2532,6 +2532,137 @@ def wrapper(*args, **kwargs):
|
2532 | 2532 | with_connectivity_check = network
|
2533 | 2533 |
|
2534 | 2534 |
|
| 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 | + |
2535 | 2666 | @contextmanager
|
2536 | 2667 | def assert_produces_warning(expected_warning=Warning, filter_level="always",
|
2537 | 2668 | clear=None, check_stacklevel=True):
|
|
0 commit comments