Skip to content
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

Fix warning about non-ascii warnings even when they are ascii #2810

Merged
merged 2 commits into from
Oct 3, 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
4 changes: 2 additions & 2 deletions _pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def _bytes_to_ascii(val):
# empty bytes crashes codecs.escape_encode (#1087)
return ''

def _ascii_escaped(val):
def ascii_escaped(val):
"""If val is pure ascii, returns it as a str(). Otherwise, escapes
bytes objects into a sequence of escaped bytes:

Expand Down Expand Up @@ -177,7 +177,7 @@ def _ascii_escaped(val):

from itertools import imap, izip # NOQA

def _ascii_escaped(val):
def ascii_escaped(val):
"""In py2 bytes and str are the same type, so return if it's a bytes
object, return it unchanged if it is a full ascii string,
otherwise escape it into its binary form.
Expand Down
10 changes: 5 additions & 5 deletions _pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from _pytest import fixtures
from _pytest import main
from _pytest.compat import (
isclass, isfunction, is_generator, _ascii_escaped,
isclass, isfunction, is_generator, ascii_escaped,
REGEX_TYPE, STRING_TYPES, NoneType, NOTSET,
get_real_func, getfslineno, safe_getattr,
safe_str, getlocation, enum,
Expand Down Expand Up @@ -922,7 +922,7 @@ def _idval(val, argname, idx, idfn, config=None):
msg += '\nUpdate your code as this will raise an error in pytest-4.0.'
warnings.warn(msg, DeprecationWarning)
if s:
return _ascii_escaped(s)
return ascii_escaped(s)

if config:
hook_id = config.hook.pytest_make_parametrize_id(
Expand All @@ -931,11 +931,11 @@ def _idval(val, argname, idx, idfn, config=None):
return hook_id

if isinstance(val, STRING_TYPES):
return _ascii_escaped(val)
return ascii_escaped(val)
elif isinstance(val, (float, int, bool, NoneType)):
return str(val)
elif isinstance(val, REGEX_TYPE):
return _ascii_escaped(val.pattern)
return ascii_escaped(val.pattern)
elif enum is not None and isinstance(val, enum.Enum):
return str(val)
elif isclass(val) and hasattr(val, '__name__'):
Expand All @@ -951,7 +951,7 @@ def _idvalset(idx, parameterset, argnames, idfn, ids, config=None):
for val, argname in zip(parameterset.values, argnames)]
return "-".join(this_id)
else:
return _ascii_escaped(ids[idx])
return ascii_escaped(ids[idx])


def idmaker(argnames, parametersets, idfn=None, ids=None, config=None):
Expand Down
4 changes: 2 additions & 2 deletions _pytest/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def catch_warnings_for_item(item):
unicode_warning = False

if compat._PY2 and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args):
new_args = [compat.safe_str(m) for m in warn_msg.args]
Copy link
Member Author

Choose a reason for hiding this comment

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

We didn't realize at the time, but this is incorrect, safe_str will return utf-8 encoded bytes, which is not ascii.

unicode_warning = warn_msg.args != new_args
new_args = [compat.ascii_escaped(m) for m in warn_msg.args]
unicode_warning = list(warn_msg.args) != new_args
warn_msg.args = new_args

msg = warnings.formatwarning(
Expand Down
1 change: 1 addition & 0 deletions changelog/2809.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Pytest no longer complains about warnings with unicode messages being non-ascii compatible even for ascii-compatible messages. As a result of this, warnings with unicode messages are converted first to an ascii representation for safety.
22 changes: 21 additions & 1 deletion testing/test_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,33 @@ def test_func(fix):
result.stdout.fnmatch_lines([
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,

'*test_py2_unicode.py:8: UserWarning: \u6d4b\u8bd5',
'*test_py2_unicode.py:8: UserWarning: \\u6d4b\\u8bd5',
'*warnings.warn(u"\u6d4b\u8bd5")',
'*warnings.py:*: UnicodeWarning: Warning is using unicode non*',
'* 1 passed, 2 warnings*',
])


def test_py2_unicode_ascii(testdir):
"""Ensure that our warning about 'unicode warnings containing non-ascii messages'
does not trigger with ascii-convertible messages"""
testdir.makeini('[pytest]')
testdir.makepyfile('''
import pytest
import warnings

@pytest.mark.filterwarnings('always')
def test_func():
warnings.warn(u"hello")
''')
result = testdir.runpytest()
result.stdout.fnmatch_lines([
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
'*warnings.warn(u"hello")',
'* 1 passed, 1 warnings in*'
])


def test_works_with_filterwarnings(testdir):
"""Ensure our warnings capture does not mess with pre-installed filters (#2430)."""
testdir.makepyfile('''
Expand Down