feat: 10865 refactor code and tests

This commit is contained in:
Volodymyr Kochetkov 2024-01-28 14:19:41 +02:00
parent 62c6f53689
commit 4806b591fc
6 changed files with 20 additions and 21 deletions

View File

@ -416,6 +416,7 @@ Vivaan Verma
Vlad Dragos
Vlad Radziuk
Vladyslav Rachek
Volodymyr Kochetkov
Volodymyr Piskun
Wei Lin
Wil Cooley

View File

@ -1 +0,0 @@
Fix a TypeError in a warning arguments call muted by warnings filter.

View File

@ -0,0 +1,2 @@
:func:`pytest.warns` now validates that warning object's ``message`` is of type `str` -- currently in Python it is possible to pass other types than `str` when creating `Warning` instances, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings. See `CPython #103577 <https://github.com/python/cpython/issues/103577>`__ for a discussion.
While this can be considered a bug in CPython, we decided to put guards in pytest as the error message produced without this check in place is confusing.

View File

@ -329,11 +329,11 @@ class WarningsChecker(WarningsRecorder):
module=w.__module__,
source=w.source,
)
# Check warnings has valid argument type
# Check warnings has valid argument type (#10865).
wrn: warnings.WarningMessage
for wrn in self:
if isinstance(wrn.message, Warning):
if not isinstance(wrn.message.args[0], str):
if not isinstance(msg := wrn.message.args[0], str):
raise TypeError(
f"Warning message must be str, got {type(wrn.message.args[0])}"
f"Warning message must be str, got {msg!r} (type {type(msg).__name__})"
)

View File

@ -1,17 +0,0 @@
from _pytest.pytester import Pytester
class TestWarningAttributes:
def test_raise_type_error(self, pytester: Pytester) -> None:
pytester.makepyfile(
"""
import pytest
import warnings
def test_example_one():
with pytest.warns(UserWarning):
warnings.warn(1)
"""
)
result = pytester.runpytest()
result.stdout.fnmatch_lines(["*1 failed*"])

View File

@ -477,3 +477,17 @@ class TestWarns:
with pytest.raises(ValueError, match="some exception"):
warnings.warn("some warning", category=FutureWarning)
raise ValueError("some exception")
def test_raise_type_error_on_non_string_warning() -> None:
"""Check pytest.warns validates warning messages are strings (#10865)."""
with pytest.raises(TypeError, match="Warning message must be str"):
with pytest.warns(UserWarning):
warnings.warn(1) # type: ignore
# Check that we get the same behavior with the stdlib, at least if filtering
# (see https://github.com/python/cpython/issues/103577 for details)
with pytest.raises(TypeError):
with warnings.catch_warnings():
warnings.filterwarnings("ignore", "test")
warnings.warn(1) # type: ignore