|
16 | 16 | ContextManager,
|
17 | 17 | List,
|
18 | 18 | Optional,
|
| 19 | + Sequence, |
19 | 20 | Tuple,
|
20 | 21 | Type,
|
21 | 22 | Union,
|
@@ -2715,65 +2716,101 @@ class for all warnings. To check that no warning is returned,
|
2715 | 2716 | __tracebackhide__ = True
|
2716 | 2717 |
|
2717 | 2718 | with warnings.catch_warnings(record=True) as w:
|
2718 |
| - |
2719 |
| - saw_warning = False |
2720 |
| - matched_message = False |
2721 |
| - |
2722 | 2719 | warnings.simplefilter(filter_level)
|
2723 | 2720 | yield w
|
2724 |
| - extra_warnings = [] |
2725 | 2721 |
|
2726 |
| - for actual_warning in w: |
| 2722 | + if expected_warning: |
2727 | 2723 | expected_warning = cast(Type[Warning], expected_warning)
|
2728 |
| - if expected_warning and issubclass( |
2729 |
| - actual_warning.category, expected_warning |
| 2724 | + _assert_caught_expected_warning( |
| 2725 | + caught_warnings=w, |
| 2726 | + expected_warning=expected_warning, |
| 2727 | + match=match, |
| 2728 | + check_stacklevel=check_stacklevel, |
| 2729 | + ) |
| 2730 | + |
| 2731 | + if raise_on_extra_warnings: |
| 2732 | + _assert_caught_no_extra_warnings( |
| 2733 | + caught_warnings=w, |
| 2734 | + expected_warning=expected_warning, |
| 2735 | + ) |
| 2736 | + |
| 2737 | + |
| 2738 | +def _assert_caught_expected_warning( |
| 2739 | + *, |
| 2740 | + caught_warnings: Sequence[warnings.WarningMessage], |
| 2741 | + expected_warning: Type[Warning], |
| 2742 | + match: Optional[str], |
| 2743 | + check_stacklevel: bool, |
| 2744 | +) -> None: |
| 2745 | + """Assert that there was the expected warning among the caught warnings.""" |
| 2746 | + saw_warning = False |
| 2747 | + matched_message = False |
| 2748 | + |
| 2749 | + for actual_warning in caught_warnings: |
| 2750 | + if issubclass(actual_warning.category, expected_warning): |
| 2751 | + saw_warning = True |
| 2752 | + |
| 2753 | + if check_stacklevel and issubclass( |
| 2754 | + actual_warning.category, (FutureWarning, DeprecationWarning) |
2730 | 2755 | ):
|
2731 |
| - saw_warning = True |
| 2756 | + _assert_raised_with_correct_stacklevel(actual_warning) |
2732 | 2757 |
|
2733 |
| - if check_stacklevel and issubclass( |
2734 |
| - actual_warning.category, (FutureWarning, DeprecationWarning) |
2735 |
| - ): |
2736 |
| - _assert_raised_with_correct_stacklevel(actual_warning) |
| 2758 | + if match is not None and re.search(match, str(actual_warning.message)): |
| 2759 | + matched_message = True |
2737 | 2760 |
|
2738 |
| - if match is not None and re.search(match, str(actual_warning.message)): |
2739 |
| - matched_message = True |
| 2761 | + if not saw_warning: |
| 2762 | + raise AssertionError( |
| 2763 | + f"Did not see expected warning of class " |
| 2764 | + f"{repr(expected_warning.__name__)}" |
| 2765 | + ) |
2740 | 2766 |
|
2741 |
| - else: |
2742 |
| - extra_warnings.append( |
2743 |
| - ( |
2744 |
| - actual_warning.category.__name__, |
2745 |
| - actual_warning.message, |
2746 |
| - actual_warning.filename, |
2747 |
| - actual_warning.lineno, |
2748 |
| - ) |
2749 |
| - ) |
| 2767 | + if match and not matched_message: |
| 2768 | + raise AssertionError( |
| 2769 | + f"Did not see warning {repr(expected_warning.__name__)} " |
| 2770 | + f"matching {match}" |
| 2771 | + ) |
2750 | 2772 |
|
2751 |
| - if expected_warning: |
2752 |
| - expected_warning = cast(Type[Warning], expected_warning) |
2753 |
| - if not saw_warning: |
2754 |
| - raise AssertionError( |
2755 |
| - f"Did not see expected warning of class " |
2756 |
| - f"{repr(expected_warning.__name__)}" |
2757 |
| - ) |
2758 | 2773 |
|
2759 |
| - if match and not matched_message: |
2760 |
| - raise AssertionError( |
2761 |
| - f"Did not see warning {repr(expected_warning.__name__)} " |
2762 |
| - f"matching {match}" |
| 2774 | +def _assert_caught_no_extra_warnings( |
| 2775 | + *, |
| 2776 | + caught_warnings: Sequence[warnings.WarningMessage], |
| 2777 | + expected_warning: Optional[Union[Type[Warning], bool]], |
| 2778 | +) -> None: |
| 2779 | + """Assert that no extra warnings apart from the expected ones are caught.""" |
| 2780 | + extra_warnings = [] |
| 2781 | + |
| 2782 | + for actual_warning in caught_warnings: |
| 2783 | + if _is_unexpected_warning(actual_warning, expected_warning): |
| 2784 | + extra_warnings.append( |
| 2785 | + ( |
| 2786 | + actual_warning.category.__name__, |
| 2787 | + actual_warning.message, |
| 2788 | + actual_warning.filename, |
| 2789 | + actual_warning.lineno, |
2763 | 2790 | )
|
2764 |
| - |
2765 |
| - if raise_on_extra_warnings and extra_warnings: |
2766 |
| - raise AssertionError( |
2767 |
| - f"Caused unexpected warning(s): {repr(extra_warnings)}" |
2768 | 2791 | )
|
2769 | 2792 |
|
| 2793 | + if extra_warnings: |
| 2794 | + raise AssertionError(f"Caused unexpected warning(s): {repr(extra_warnings)}") |
| 2795 | + |
| 2796 | + |
| 2797 | +def _is_unexpected_warning( |
| 2798 | + actual_warning: warnings.WarningMessage, |
| 2799 | + expected_warning: Optional[Union[Type[Warning], bool]], |
| 2800 | +) -> bool: |
| 2801 | + """Check if the actual warning issued is unexpected.""" |
| 2802 | + if actual_warning and not expected_warning: |
| 2803 | + return True |
| 2804 | + expected_warning = cast(Type[Warning], expected_warning) |
| 2805 | + return bool(not issubclass(actual_warning.category, expected_warning)) |
| 2806 | + |
2770 | 2807 |
|
2771 | 2808 | def _assert_raised_with_correct_stacklevel(
|
2772 | 2809 | actual_warning: warnings.WarningMessage,
|
2773 | 2810 | ) -> None:
|
2774 | 2811 | from inspect import getframeinfo, stack
|
2775 | 2812 |
|
2776 |
| - caller = getframeinfo(stack()[3][0]) |
| 2813 | + caller = getframeinfo(stack()[4][0]) |
2777 | 2814 | msg = (
|
2778 | 2815 | "Warning not set with correct stacklevel. "
|
2779 | 2816 | f"File where warning is raised: {actual_warning.filename} != "
|
|
0 commit comments