1 # encoding: utf-8 2 """Tests for IPython.utils.text""" 3 4 #----------------------------------------------------------------------------- 5 # Copyright (C) 2011 The IPython Development Team 6 # 7 # Distributed under the terms of the BSD License. The full license is in 8 # the file COPYING, distributed as part of this software. 9 #----------------------------------------------------------------------------- 10 11 #----------------------------------------------------------------------------- 12 # Imports 13 #----------------------------------------------------------------------------- 14 15 import os 16 import math 17 import random 18 19 from pathlib import Path 20 21 import pytest 22 23 from IPython.utils import text 24 25 #----------------------------------------------------------------------------- 26 # Globals 27 #----------------------------------------------------------------------------- 28 29 30 @pytest.mark.parametrize( 31 "expected, width, row_first, spread", 32 ( 33 ( 34 "aaaaa bbbbb ccccc ddddd\n", 35 80, 36 False, 37 False, 38 ), 39 ( 40 "aaaaa ccccc\nbbbbb ddddd\n", 41 25, 42 False, 43 False, 44 ), 45 ( 46 "aaaaa ccccc\nbbbbb ddddd\n", 47 12, 48 False, 49 False, 50 ), 51 ( 52 "aaaaa\nbbbbb\nccccc\nddddd\n", 53 10, 54 False, 55 False, 56 ), 57 ( 58 "aaaaa bbbbb ccccc ddddd\n", 59 80, 60 True, 61 False, 62 ), 63 ( 64 "aaaaa bbbbb\nccccc ddddd\n", 65 25, 66 True, 67 False, 68 ), 69 ( 70 "aaaaa bbbbb\nccccc ddddd\n", 71 12, 72 True, 73 False, 74 ), 75 ( 76 "aaaaa\nbbbbb\nccccc\nddddd\n", 77 10, 78 True, 79 False, 80 ), 81 ( 82 "aaaaa bbbbb ccccc ddddd\n", 83 40, 84 False, 85 True, 86 ), 87 ( 88 "aaaaa ccccc\nbbbbb ddddd\n", 89 20, 90 False, 91 True, 92 ), 93 ( 94 "aaaaa ccccc\nbbbbb ddddd\n", 95 12, 96 False, 97 True, 98 ), 99 ( 100 "aaaaa\nbbbbb\nccccc\nddddd\n", 101 10, 102 False, 103 True, 104 ), 105 ), 106 ) 107 def test_columnize(expected, width, row_first, spread): 108 """Basic columnize tests.""" 109 size = 5 110 items = [l*size for l in 'abcd'] 111 with pytest.warns(PendingDeprecationWarning): 112 out = text.columnize( 113 items, displaywidth=width, row_first=row_first, spread=spread 114 ) 115 assert out == expected 116 117 118 def test_columnize_random(): 119 """Test with random input to hopefully catch edge case """ 120 for row_first in [True, False]: 121 for nitems in [random.randint(2,70) for i in range(2,20)]: 122 displaywidth = random.randint(20,200) 123 rand_len = [random.randint(2,displaywidth) for i in range(nitems)] 124 items = ['x'*l for l in rand_len] 125 with pytest.warns(PendingDeprecationWarning): 126 out = text.columnize( 127 items, row_first=row_first, displaywidth=displaywidth 128 ) 129 longer_line = max([len(x) for x in out.split("\n")]) 130 longer_element = max(rand_len) 131 assert longer_line <= displaywidth, ( 132 f"Columnize displayed something lager than displaywidth : {longer_line}\n" 133 f"longer element : {longer_element}\n" 134 f"displaywidth : {displaywidth}\n" 135 f"number of element : {nitems}\n" 136 f"size of each element : {rand_len}\n" 137 f"row_first={row_first}\n" 138 ) 139 140 141 @pytest.mark.parametrize("row_first", [True, False]) 142 def test_columnize_medium(row_first): 143 """Test with inputs than shouldn't be wider than 80""" 144 size = 40 145 items = [l*size for l in 'abc'] 146 with pytest.warns(PendingDeprecationWarning): 147 out = text.columnize(items, row_first=row_first, displaywidth=80) 148 assert out == "\n".join(items + [""]), "row_first={0}".format(row_first) 149 150 151 @pytest.mark.parametrize("row_first", [True, False]) 152 def test_columnize_long(row_first): 153 """Test columnize with inputs longer than the display window""" 154 size = 11 155 items = [l*size for l in 'abc'] 156 with pytest.warns(PendingDeprecationWarning): 157 out = text.columnize(items, row_first=row_first, displaywidth=size - 1) 158 assert out == "\n".join(items + [""]), "row_first={0}".format(row_first) 159 160 161 def eval_formatter_check(f): 162 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os, u=u"café", b="café") 163 s = f.format("{n} {n//4} {stuff.split()[0]}", **ns) 164 assert s == "12 3 hello" 165 s = f.format(" ".join(["{n//%i}" % i for i in range(1, 8)]), **ns) 166 assert s == "12 6 4 3 2 2 1" 167 s = f.format("{[n//i for i in range(1,8)]}", **ns) 168 assert s == "[12, 6, 4, 3, 2, 2, 1]" 169 s = f.format("{stuff!s}", **ns) 170 assert s == ns["stuff"] 171 s = f.format("{stuff!r}", **ns) 172 assert s == repr(ns["stuff"]) 173 174 # Check with unicode: 175 s = f.format("{u}", **ns) 176 assert s == ns["u"] 177 # This decodes in a platform dependent manner, but it shouldn't error out 178 s = f.format("{b}", **ns) 179 180 pytest.raises(NameError, f.format, "{dne}", **ns) 181 182 183 def eval_formatter_slicing_check(f): 184 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os) 185 s = f.format(" {stuff.split()[:]} ", **ns) 186 assert s == " ['hello', 'there'] " 187 s = f.format(" {stuff.split()[::-1]} ", **ns) 188 assert s == " ['there', 'hello'] " 189 s = f.format("{stuff[::2]}", **ns) 190 assert s == ns["stuff"][::2] 191 192 pytest.raises(SyntaxError, f.format, "{n:x}", **ns) 193 194 def eval_formatter_no_slicing_check(f): 195 ns = dict(n=12, pi=math.pi, stuff="hello there", os=os) 196 197 s = f.format("{n:x} {pi**2:+f}", **ns) 198 assert s == "c +9.869604" 199 200 s = f.format("{stuff[slice(1,4)]}", **ns) 201 assert s == "ell" 202 203 s = f.format("{a[:]}", a=[1, 2]) 204 assert s == "[1, 2]" 205 206 def test_eval_formatter(): 207 f = text.EvalFormatter() 208 eval_formatter_check(f) 209 eval_formatter_no_slicing_check(f) 210 211 def test_full_eval_formatter(): 212 f = text.FullEvalFormatter() 213 eval_formatter_check(f) 214 eval_formatter_slicing_check(f) 215 216 def test_dollar_formatter(): 217 f = text.DollarFormatter() 218 eval_formatter_check(f) 219 eval_formatter_slicing_check(f) 220 221 ns = dict(n=12, pi=math.pi, stuff='hello there', os=os) 222 s = f.format("$n", **ns) 223 assert s == "12" 224 s = f.format("$n.real", **ns) 225 assert s == "12" 226 s = f.format("$n/{stuff[:5]}", **ns) 227 assert s == "12/hello" 228 s = f.format("$n $$HOME", **ns) 229 assert s == "12 $HOME" 230 s = f.format("${foo}", foo="HOME") 231 assert s == "$HOME" 232 233 234 def test_strip_email(): 235 src = """\ 236 >> >>> def f(x): 237 >> ... return x+1 238 >> ... 239 >> >>> zz = f(2.5)""" 240 cln = """\ 241 >>> def f(x): 242 ... return x+1 243 ... 244 >>> zz = f(2.5)""" 245 assert text.strip_email_quotes(src) == cln 246 247 248 def test_strip_email2(): 249 src = "> > > list()" 250 cln = "list()" 251 assert text.strip_email_quotes(src) == cln 252 253 254 def test_LSString(): 255 lss = text.LSString("abc\ndef") 256 assert lss.l == ["abc", "def"] 257 assert lss.s == "abc def" 258 lss = text.LSString(os.getcwd()) 259 assert isinstance(lss.p[0], Path) 260 261 262 def test_SList(): 263 sl = text.SList(["a 11", "b 1", "a 2"]) 264 assert sl.n == "a 11\nb 1\na 2" 265 assert sl.s == "a 11 b 1 a 2" 266 assert sl.grep(lambda x: x.startswith("a")) == text.SList(["a 11", "a 2"]) 267 assert sl.fields(0) == text.SList(["a", "b", "a"]) 268 assert sl.sort(field=1, nums=True) == text.SList(["b 1", "a 2", "a 11"]) 269