Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ enhancement2
Other enhancements
^^^^^^^^^^^^^^^^^^
- :func:`DataFrame.to_excel` now raises an ``UserWarning`` when the character count in a cell exceeds Excel's limitation of 32767 characters (:issue:`56954`)
- :func:`assert_produces_warning` now accepts warning message match for every expected warning. A must_find_all_warnings keyword argument was added, to make the function check all expected warnings. (:issue:`56555`)
- :func:`read_stata` now returns ``datetime64`` resolutions better matching those natively stored in the stata format (:issue:`55642`)
-

.. ---------------------------------------------------------------------------
.. _whatsnew_300.notable_bug_fixes:
Expand Down
54 changes: 44 additions & 10 deletions pandas/_testing/_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def assert_produces_warning(
] = "always",
check_stacklevel: bool = True,
raise_on_extra_warnings: bool = True,
match: str | None = None,
match: str | tuple[str | None, ...] | None = None,
must_find_all_warnings: bool = False,
) -> Generator[list[warnings.WarningMessage], None, None]:
"""
Context manager for running code expected to either raise a specific warning,
Expand Down Expand Up @@ -68,8 +69,17 @@ class for all warnings. To raise multiple types of exceptions,
raise_on_extra_warnings : bool, default True
Whether extra warnings not of the type `expected_warning` should
cause the test to fail.
match : str, optional
Match warning message.
match : {str, tuple[str, ...]}, optional
Match warning message. If it's a tuple, it has to be the size of
`expected_warning`. If additionally `must_find_all_warnings` is
True, each expected warning's message gets matched with a respective
match. Otherwise, multiple values get treated as an alternative.
must_find_all_warnings : bool, default False
If True and `expected_warning` is a tuple, each expected warning
type must get encountered. Otherwise, even one expected warning
results in success.

.. versionadded:: 3.0.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't in the documentation; this line can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


Examples
--------
Expand Down Expand Up @@ -99,13 +109,37 @@ class for all warnings. To raise multiple types of exceptions,
yield w
finally:
if expected_warning:
expected_warning = cast(type[Warning], expected_warning)
_assert_caught_expected_warning(
caught_warnings=w,
expected_warning=expected_warning,
match=match,
check_stacklevel=check_stacklevel,
)
if type(expected_warning) == tuple and must_find_all_warnings:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use isinstance here I think, hopefully making the cast below unnecessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, that helped to remove most of the casts.

expected_warning = cast(tuple[type[Warning]], expected_warning)
match = (
match
if type(match) == tuple
else tuple(
cast(str | None, match)
for i in range(len(expected_warning))
)
)
for warning_type, warning_match in zip(expected_warning, match):
_assert_caught_expected_warning(
caught_warnings=w,
expected_warning=warning_type,
match=warning_match,
check_stacklevel=check_stacklevel,
)
else:
expected_warning = cast(type[Warning], expected_warning)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can still be a tuple, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right. I believe this was originally done, to suppress _assert_caught_expected_warning not accepting tuples. I changed that and fixed some issues that arose because of that now.

match = cast(
str,
"|".join(m for m in match if m)
if type(match) == tuple
else match,
)
_assert_caught_expected_warning(
caught_warnings=w,
expected_warning=expected_warning,
match=match,
check_stacklevel=check_stacklevel,
)
if raise_on_extra_warnings:
_assert_caught_no_extra_warnings(
caught_warnings=w,
Expand Down