Skip to content

Commit 2abd005

Browse files
authored
Merge pull request #4195 from nicoddemus/issue-3691
Use safe_str() to format warning message about unicode in Python 2
2 parents 366b883 + 864d7fe commit 2abd005

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

changelog/3691.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Python 2: safely format warning message about passing unicode strings to ``warnings.warn``, which may cause
2+
surprising ``MemoryError`` exception when monkey patching ``warnings.warn`` itself.

src/_pytest/warnings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def warning_record_to_str(warning_message):
123123
if unicode_warning:
124124
warnings.warn(
125125
"Warning is using unicode non convertible to ascii, "
126-
"converting to a safe representation:\n %s" % msg,
126+
"converting to a safe representation:\n {!r}".format(compat.safe_str(msg)),
127127
UnicodeWarning,
128128
)
129129
return msg

testing/test_warnings.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import sys
55

6+
import six
7+
68
import pytest
79

810

@@ -562,3 +564,30 @@ def test_hidden_by_system(self, testdir, monkeypatch):
562564
monkeypatch.setenv(str("PYTHONWARNINGS"), str("once::UserWarning"))
563565
result = testdir.runpytest_subprocess()
564566
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
567+
568+
569+
@pytest.mark.skipif(six.PY3, reason="Python 2 only issue")
570+
def test_infinite_loop_warning_against_unicode_usage_py2(testdir):
571+
"""
572+
We need to be careful when raising the warning about unicode usage with "warnings.warn"
573+
because it might be overwritten by users and this itself causes another warning (#3691).
574+
"""
575+
testdir.makepyfile(
576+
"""
577+
# -*- coding: utf8 -*-
578+
from __future__ import unicode_literals
579+
import warnings
580+
import pytest
581+
582+
def _custom_showwarning(message, *a, **b):
583+
return "WARNING: {}".format(message)
584+
585+
warnings.formatwarning = _custom_showwarning
586+
587+
@pytest.mark.filterwarnings("default")
588+
def test_custom_warning_formatter():
589+
warnings.warn("¥")
590+
"""
591+
)
592+
result = testdir.runpytest_subprocess()
593+
result.stdout.fnmatch_lines(["*1 passed, * warnings in*"])

tox.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ envlist =
1818

1919
[testenv]
2020
commands =
21-
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof
21+
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof {posargs}
2222
coverage: coverage combine
2323
coverage: coverage report
2424
passenv = USER USERNAME COVERAGE_* TRAVIS
@@ -41,7 +41,7 @@ deps =
4141
py27: mock
4242
nose
4343
commands =
44-
pytest -n auto --runpytest=subprocess
44+
pytest -n auto --runpytest=subprocess {posargs}
4545

4646

4747
[testenv:linting]
@@ -58,7 +58,7 @@ deps =
5858
hypothesis>=3.56
5959
{env:_PYTEST_TOX_EXTRA_DEP:}
6060
commands =
61-
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto
61+
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto {posargs}
6262

6363
[testenv:py36-xdist]
6464
# NOTE: copied from above due to https://github.com/tox-dev/tox/issues/706.

0 commit comments

Comments
 (0)