-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #336 from pv/unicode-fix
Fix encoding-fallback printing on Py3
- Loading branch information
Showing
2 changed files
with
123 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
# -*- coding: utf-8 -*- | ||
# Licensed under a 3-clause BSD style license - see LICENSE.rst | ||
|
||
from __future__ import (absolute_import, division, print_function, | ||
unicode_literals) | ||
|
||
import six | ||
import io | ||
import sys | ||
import locale | ||
import itertools | ||
import pytest | ||
from contextlib import contextmanager | ||
|
||
from asv.console import _write_with_fallback, color_print | ||
|
||
|
||
def test_write_with_fallback(capfd): | ||
|
||
def check_write(value, expected, stream_encoding, preferred_encoding): | ||
old_getpreferredencoding = locale.getpreferredencoding | ||
try: | ||
locale.getpreferredencoding = lambda: preferred_encoding | ||
|
||
# Check writing to io.StringIO | ||
stream = io.StringIO() | ||
_write_with_fallback(value, stream.write, stream) | ||
assert stream.getvalue() == value | ||
|
||
# Check writing to a text stream | ||
buf = io.BytesIO() | ||
stream = io.TextIOWrapper(buf, encoding=stream_encoding) | ||
_write_with_fallback(value, stream.write, stream) | ||
stream.flush() | ||
got = buf.getvalue() | ||
assert got == expected | ||
|
||
# Check writing to a byte stream (no stream encoding, so | ||
# it should write in locale encoding) | ||
if stream_encoding == preferred_encoding: | ||
buf = io.BytesIO() | ||
_write_with_fallback(value, buf.write, buf) | ||
got = buf.getvalue() | ||
assert got == expected | ||
|
||
# Check writing to a file | ||
with io.open('tmp.txt', 'w', encoding=stream_encoding) as stream: | ||
_write_with_fallback(value, stream.write, stream) | ||
with open('tmp.txt', 'rb') as stream: | ||
got = stream.read() | ||
assert got == expected | ||
|
||
# Check writing to Py2 files | ||
if not six.PY3: | ||
if stream_encoding == preferred_encoding: | ||
# No stream encoding: write in locale encoding | ||
for mode in ['w', 'wb']: | ||
with open('tmp.txt', mode) as stream: | ||
_write_with_fallback(value, stream.write, stream) | ||
with open('tmp.txt', 'rb') as stream: | ||
got = stream.read() | ||
assert got == expected | ||
finally: | ||
locale.getpreferredencoding = old_getpreferredencoding | ||
|
||
# What is printed should follow the following rules: | ||
# | ||
# - Try printing in stream encoding. | ||
# - Try printing in locale preferred encoding. | ||
# - Otherwise, map characters produced by asv to ascii equivalents, and | ||
# - Try to print in latin1 | ||
# - Try to print in ascii, replacing all non-ascii characters | ||
encodings = ['utf-8', 'latin1', 'ascii', 'euc-jp'] | ||
strings = ["helloμ", "hello·", "hello難", "helloä"] | ||
repmap = {"helloμ": "hellou", "hello·": "hello-"} | ||
|
||
for pref_enc, stream_enc, s in itertools.product(encodings, encodings, strings): | ||
expected = None | ||
for enc in [stream_enc, pref_enc]: | ||
try: | ||
expected = s.encode(enc) | ||
break | ||
except UnicodeError: | ||
pass | ||
else: | ||
s2 = repmap.get(s, s) | ||
try: | ||
expected = s2.encode('latin1') | ||
except UnicodeError: | ||
expected = s2.encode('ascii', 'replace') | ||
|
||
check_write(s, expected, stream_enc, pref_enc) | ||
|
||
# Should not bail out on bytes input | ||
_write_with_fallback("a".encode('ascii'), sys.stdout.write, sys.stdout) | ||
out, err = capfd.readouterr() | ||
assert out == "a" | ||
|
||
|
||
def test_color_print_nofail(capfd): | ||
# Try out color print | ||
|
||
color_print("hello", "red") | ||
color_print("indeed難", "blue") | ||
color_print(b"really\xfe", "green", "not really") | ||
|
||
out, err = capfd.readouterr() | ||
assert 'hello' in out | ||
assert 'indeed' in out | ||
assert 'really' in out | ||
assert 'not really' in out |