Skip to content

Correct warnings that contains Unicode message #2437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
3.1.1 (unreleased)
==================

* Fix encoding errors for unicode warnings in Python 2.


3.1.0 (2017-05-22)
==================

Expand Down
2 changes: 2 additions & 0 deletions _pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def isclass(object):
import codecs
imap = map
STRING_TYPES = bytes, str
UNICODE_TYPES = str,

def _escape_strings(val):
"""If val is pure ascii, returns it as a str(). Otherwise, escapes
Expand Down Expand Up @@ -157,6 +158,7 @@ def _escape_strings(val):
return val.encode('unicode_escape').decode('ascii')
else:
STRING_TYPES = bytes, str, unicode
UNICODE_TYPES = unicode,

from itertools import imap # NOQA

Expand Down
17 changes: 16 additions & 1 deletion _pytest/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import pytest

from _pytest import compat


def _setoption(wmod, arg):
"""
Expand Down Expand Up @@ -61,11 +63,24 @@ def catch_warnings_for_item(item):
yield

for warning in log:
warn_msg = warning.message
unicode_warning = False

if compat._PY2 and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args):
warn_msg.args = [compat.safe_str(m) for m in warn_msg.args]
unicode_warning = True

msg = warnings.formatwarning(
warning.message, warning.category,
warn_msg, warning.category,
warning.filename, warning.lineno, warning.line)
item.warn("unused", msg)

if unicode_warning:
warnings.warn(
"This warning %s is broken as it's message is not a str instance"
"(after all this is a stdlib problem workaround)" % msg,
UnicodeWarning)


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item):
Expand Down
60 changes: 60 additions & 0 deletions testing/test_warnings.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# -*- coding: utf8 -*-
from __future__ import unicode_literals

import sys

import pytest


Expand Down Expand Up @@ -106,3 +111,58 @@ def test_ignore(testdir, pyfile_with_warnings, method):
])
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()



@pytest.mark.skipif(sys.version_info < (3, 0),
reason='warnings message is unicode is ok in python3')
def test_unicode(testdir, pyfile_with_warnings):
testdir.makepyfile('''
# -*- coding: utf8 -*-
import warnings
import pytest


@pytest.fixture
def fix():
warnings.warn(u"测试")
yield

def test_func(fix):
pass
''')
result = testdir.runpytest()
result.stdout.fnmatch_lines([
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,

'*test_unicode.py:8: UserWarning: \u6d4b\u8bd5',
'*warnings.warn(u"\u6d4b\u8bd5")',
'* 1 passed, 1 warnings*',
])


@pytest.mark.skipif(sys.version_info >= (3, 0),
reason='warnings message is broken as it is not str instance')
def test_py2_unicode(testdir, pyfile_with_warnings):
testdir.makepyfile('''
# -*- coding: utf8 -*-
import warnings
import pytest


@pytest.fixture
def fix():
warnings.warn(u"测试")
yield

def test_func(fix):
pass
''')
result = testdir.runpytest()
result.stdout.fnmatch_lines([
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,

'*test_py2_unicode.py:8: UserWarning: \u6d4b\u8bd5',
'*warnings.warn(u"\u6d4b\u8bd5")',
'*warnings.py:82: UnicodeWarning: This warning*\u6d4b\u8bd5',
'* 1 passed, 2 warnings*',
])