1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
# Licensed under a 3-clause BSD style license - see LICENSE.rst
# -*- coding: utf-8 -*-
# TEST_UNICODE_LITERALS
from __future__ import (absolute_import, division, print_function,
unicode_literals)
from ...extern import six # pylint: disable=W0611
from ...extern.six import next
from ...extern.six.moves import range
import io
import locale
from ...tests.helper import pytest
from .. import console
from ... import units as u
class FakeTTY(io.StringIO):
"""IOStream that fakes a TTY; provide an encoding to emulate an output
stream with a specific encoding.
"""
def __new__(cls, encoding=None):
# Return a new subclass of FakeTTY with the requested encoding
if encoding is None:
return super(FakeTTY, cls).__new__(cls)
# Since we're using unicode_literals in this module ensure that this is
# a 'str' object (since a class name can't be unicode in Python 2.7)
encoding = str(encoding)
cls = type(encoding.title() + cls.__name__, (cls,),
{'encoding': encoding})
return cls.__new__(cls)
def __init__(self, encoding=None):
super(FakeTTY, self).__init__()
def write(self, s):
if isinstance(s, bytes):
# Just allow this case to work
s = s.decode('latin-1')
elif self.encoding is not None:
s.encode(self.encoding)
return super(FakeTTY, self).write(s)
def isatty(self):
return True
def test_fake_tty():
# First test without a specified encoding; we should be able to write
# arbitrary unicode strings
f1 = FakeTTY()
assert f1.isatty()
f1.write('☃')
assert f1.getvalue() == '☃'
# Now test an ASCII-only TTY--it should raise a UnicodeEncodeError when
# trying to write a string containing non-ASCII characters
f2 = FakeTTY('ascii')
assert f2.isatty()
assert f2.__class__.__name__ == 'AsciiFakeTTY'
assert pytest.raises(UnicodeEncodeError, f2.write, '☃')
assert f2.getvalue() == ''
@pytest.mark.skipif(str("sys.platform.startswith('win')"))
def test_color_text():
assert console._color_text("foo", "green") == '\033[0;32mfoo\033[0m'
def test_color_print():
# This stuff is hard to test, at least smoke test it
console.color_print("foo", "green")
console.color_print("foo", "green", "bar", "red")
def test_color_print2():
# Test that this automatically detects that io.StringIO is
# not a tty
stream = io.StringIO()
console.color_print("foo", "green", file=stream)
assert stream.getvalue() == 'foo\n'
stream = io.StringIO()
console.color_print("foo", "green", "bar", "red", "baz", file=stream)
assert stream.getvalue() == 'foobarbaz\n'
@pytest.mark.skipif(str("sys.platform.startswith('win')"))
def test_color_print3():
# Test that this thinks the FakeTTY is a tty and applies colors.
stream = FakeTTY()
console.color_print("foo", "green", file=stream)
assert stream.getvalue() == '\x1b[0;32mfoo\x1b[0m\n'
stream = FakeTTY()
console.color_print("foo", "green", "bar", "red", "baz", file=stream)
assert stream.getvalue() == '\x1b[0;32mfoo\x1b[0m\x1b[0;31mbar\x1b[0mbaz\n'
def test_color_print_unicode():
console.color_print("überbær", "red")
def test_color_print_invalid_color():
console.color_print("foo", "unknown")
@pytest.mark.skipif(str('not six.PY2'))
def test_color_print_no_default_encoding():
"""Regression test for #1244
In some environments `locale.getpreferredencoding` can return ``''``;
make sure there are some reasonable fallbacks.
"""
# Not sure of a reliable way to force getpreferredencoding() to return
# an empty string other than to temporarily patch it
orig_func = locale.getpreferredencoding
locale.getpreferredencoding = lambda: ''
try:
# Try printing a string that can be utf-8 decoded (the default)
stream = io.StringIO()
console.color_print(b'\xe2\x98\x83', 'white', file=stream)
assert stream.getvalue() == '☃\n'
# Test the latin-1 fallback
stream = io.StringIO()
console.color_print(b'\xcd\xef', 'red', file=stream)
assert stream.getvalue() == 'Íï\n'
finally:
locale.getpreferredencoding = orig_func
def test_spinner_non_unicode_console():
"""Regression test for #1760
Ensures that the spinner can fall go into fallback mode when using the
unicode spinner on a terminal whose default encoding cannot encode the
unicode characters.
"""
stream = FakeTTY('ascii')
chars = console.Spinner._default_unicode_chars
with console.Spinner("Reticulating splines", file=stream,
chars=chars) as s:
next(s)
def test_progress_bar():
# This stuff is hard to test, at least smoke test it
with console.ProgressBar(50) as bar:
for i in range(50):
bar.update()
def test_progress_bar2():
for x in console.ProgressBar(range(50)):
pass
def test_progress_bar3():
def do_nothing(*args, **kwargs):
pass
console.ProgressBar.map(do_nothing, range(50))
def test_zero_progress_bar():
with console.ProgressBar(0) as bar:
pass
def test_progress_bar_as_generator():
sum = 0
for x in console.ProgressBar(range(50)):
sum += x
assert sum == 1225
sum = 0
for x in console.ProgressBar(50):
sum += x
assert sum == 1225
@pytest.mark.parametrize(("seconds","string"),
[(864088," 1w 3d"),
(187213, " 2d 4h"),
(3905, " 1h 5m"),
(64, " 1m 4s"),
(15, " 15s"),
(2, " 2s")]
)
def test_human_time(seconds, string):
human_time = console.human_time(seconds)
assert human_time == string
@pytest.mark.parametrize(("size","string"),
[(8640882,"8.6M"),
(187213, "187k"),
(3905, "3.9k"),
(64, " 64 "),
(2, " 2 "),
(10*u.GB, " 10G")]
)
def test_human_file_size(size, string):
human_time = console.human_file_size(size)
assert human_time == string
@pytest.mark.parametrize("size", (50*u.km, 100*u.g))
def test_bad_human_file_size(size):
assert pytest.raises(u.UnitConversionError, console.human_file_size, size)
|