From c39689da41eee6656d2956d20c09b6725151583d Mon Sep 17 00:00:00 2001 From: wanghui Date: Thu, 25 May 2017 17:59:42 +0800 Subject: [PATCH 1/3] Correct warnings with unicode message. --- _pytest/warnings.py | 4 +++- testing/test_warnings.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/_pytest/warnings.py b/_pytest/warnings.py index bfa2b0087..7596b0098 100644 --- a/_pytest/warnings.py +++ b/_pytest/warnings.py @@ -5,6 +5,8 @@ from contextlib import contextmanager import pytest +from _pytest import compat + def _setoption(wmod, arg): """ @@ -62,7 +64,7 @@ def catch_warnings_for_item(item): for warning in log: msg = warnings.formatwarning( - warning.message, warning.category, + compat.safe_str(warning.message), warning.category, warning.filename, warning.lineno, warning.line) item.warn("unused", msg) diff --git a/testing/test_warnings.py b/testing/test_warnings.py index e0baed8d1..85fda430e 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -1,3 +1,6 @@ +# -*- coding: utf8 -*- +from __future__ import unicode_literals + import pytest @@ -106,3 +109,29 @@ def test_ignore(testdir, pyfile_with_warnings, method): ]) assert WARNINGS_SUMMARY_HEADER not in result.stdout.str() + + +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*', + ]) + From d7a5c5716f2386c083a2658708c4a3d9eda522c4 Mon Sep 17 00:00:00 2001 From: wanghui Date: Fri, 26 May 2017 13:12:02 +0800 Subject: [PATCH 2/3] Add UnicodeWarning for unicode warnings in Python2 --- _pytest/compat.py | 2 ++ _pytest/warnings.py | 15 ++++++++++++++- testing/test_warnings.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/_pytest/compat.py b/_pytest/compat.py index 25610b645..8c200af5f 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -126,6 +126,7 @@ if _PY3: 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 @@ -157,6 +158,7 @@ if _PY3: return val.encode('unicode_escape').decode('ascii') else: STRING_TYPES = bytes, str, unicode + UNICODE_TYPES = unicode, from itertools import imap # NOQA diff --git a/_pytest/warnings.py b/_pytest/warnings.py index 7596b0098..cbed43b8f 100644 --- a/_pytest/warnings.py +++ b/_pytest/warnings.py @@ -63,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( - compat.safe_str(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): diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 85fda430e..df9c4cdc4 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -1,6 +1,8 @@ # -*- coding: utf8 -*- from __future__ import unicode_literals +import sys + import pytest @@ -111,6 +113,8 @@ def test_ignore(testdir, pyfile_with_warnings, method): +@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 -*- @@ -135,3 +139,30 @@ def test_unicode(testdir, pyfile_with_warnings): '* 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*', + ]) From 53add4435f64363cb2d79299013ea850024dcd86 Mon Sep 17 00:00:00 2001 From: wanghui Date: Fri, 26 May 2017 13:14:42 +0800 Subject: [PATCH 3/3] Add ChangeLog --- CHANGELOG.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9009d575a..9133d5f5b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,9 @@ +3.1.1 (unreleased) +================== + +* Fix encoding errors for unicode warnings in Python 2. + + 3.1.0 (2017-05-22) ==================