run-strings.test 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. # Test cases for strings (compile and run)
  2. [case testStrBasics]
  3. from typing import Tuple
  4. def f() -> str:
  5. return 'some string'
  6. def g() -> str:
  7. return 'some\a \v \t \x7f " \n \0string 🐍'
  8. def tostr(x: int) -> str:
  9. return str(x)
  10. def booltostr(x: bool) -> str:
  11. return str(x)
  12. def concat(x: str, y: str) -> str:
  13. return x + y
  14. def eq(x: str) -> int:
  15. if x == 'foo':
  16. return 0
  17. elif x != 'bar':
  18. return 1
  19. return 2
  20. def match(x: str, y: str) -> Tuple[bool, bool]:
  21. return (x.startswith(y), x.endswith(y))
  22. [file driver.py]
  23. from native import f, g, tostr, booltostr, concat, eq, match
  24. import sys
  25. assert f() == 'some string'
  26. assert f() is sys.intern('some string')
  27. assert g() == 'some\a \v \t \x7f " \n \0string 🐍'
  28. assert tostr(57) == '57'
  29. assert concat('foo', 'bar') == 'foobar'
  30. assert booltostr(True) == 'True'
  31. assert booltostr(False) == 'False'
  32. assert eq('foo') == 0
  33. assert eq('zar') == 1
  34. assert eq('bar') == 2
  35. assert int(tostr(0)) == 0
  36. assert int(tostr(20)) == 20
  37. assert match('', '') == (True, True)
  38. assert match('abc', '') == (True, True)
  39. assert match('abc', 'a') == (True, False)
  40. assert match('abc', 'c') == (False, True)
  41. assert match('', 'abc') == (False, False)
  42. [case testStringOps]
  43. from typing import List, Optional
  44. def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]:
  45. if sep is not None:
  46. if max_split is not None:
  47. return s.split(sep, max_split)
  48. else:
  49. return s.split(sep)
  50. return s.split()
  51. ss = "abc abcd abcde abcdef"
  52. def test_split() -> None:
  53. assert do_split(ss) == ["abc", "abcd", "abcde", "abcdef"]
  54. assert do_split(ss, " ") == ["abc", "abcd", "abcde", "abcdef"]
  55. assert do_split(ss, "-") == ["abc abcd abcde abcdef"]
  56. assert do_split(ss, " ", -1) == ["abc", "abcd", "abcde", "abcdef"]
  57. assert do_split(ss, " ", 0) == ["abc abcd abcde abcdef"]
  58. assert do_split(ss, " ", 1) == ["abc", "abcd abcde abcdef"]
  59. assert do_split(ss, " ", 2) == ["abc", "abcd", "abcde abcdef"]
  60. def getitem(s: str, index: int) -> str:
  61. return s[index]
  62. from testutil import assertRaises
  63. s = "abc"
  64. def test_getitem() -> None:
  65. assert getitem(s, 0) == "a"
  66. assert getitem(s, 1) == "b"
  67. assert getitem(s, 2) == "c"
  68. assert getitem(s, -3) == "a"
  69. assert getitem(s, -2) == "b"
  70. assert getitem(s, -1) == "c"
  71. with assertRaises(IndexError, "string index out of range"):
  72. getitem(s, 4)
  73. with assertRaises(IndexError, "string index out of range"):
  74. getitem(s, -4)
  75. def str_to_int(s: str, base: Optional[int] = None) -> int:
  76. if base:
  77. return int(s, base)
  78. else:
  79. return int(s)
  80. def test_str_to_int() -> None:
  81. assert str_to_int("1") == 1
  82. assert str_to_int("10") == 10
  83. assert str_to_int("a", 16) == 10
  84. assert str_to_int("1a", 16) == 26
  85. with assertRaises(ValueError, "invalid literal for int() with base 10: 'xyz'"):
  86. str_to_int("xyz")
  87. def test_slicing() -> None:
  88. # Use dummy adds to avoid constant folding
  89. zero = int()
  90. two = zero + 2
  91. s = "foobar" + str()
  92. assert s[two:] == "obar"
  93. assert s[:two] == "fo"
  94. assert s[two:-two] == "ob"
  95. assert s[two:two] == ""
  96. assert s[two:two + 1] == "o"
  97. assert s[-two:] == "ar"
  98. assert s[:-two] == "foob"
  99. assert s[:] == "foobar"
  100. assert s[two:333] == "obar"
  101. assert s[333:two] == ""
  102. assert s[two:-333] == ""
  103. assert s[-333:two] == "fo"
  104. big_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000
  105. assert s[1:big_int] == "oobar"
  106. assert s[big_int:] == ""
  107. assert s[-big_int:-1] == "fooba"
  108. def test_str_replace() -> None:
  109. a = "foofoofoo"
  110. assert a.replace("foo", "bar") == "barbarbar"
  111. assert a.replace("foo", "bar", -1) == "barbarbar"
  112. assert a.replace("foo", "bar", 1) == "barfoofoo"
  113. assert a.replace("foo", "bar", 4) == "barbarbar"
  114. assert a.replace("aaa", "bar") == "foofoofoo"
  115. assert a.replace("ofo", "xyzw") == "foxyzwxyzwo"
  116. def is_true(x: str) -> bool:
  117. if x:
  118. return True
  119. else:
  120. return False
  121. def is_true2(x: str) -> bool:
  122. return bool(x)
  123. def is_false(x: str) -> bool:
  124. if not x:
  125. return True
  126. else:
  127. return False
  128. def test_str_to_bool() -> None:
  129. assert is_false('')
  130. assert not is_true('')
  131. assert not is_true2('')
  132. for x in 'a', 'foo', 'bar', 'some string':
  133. assert is_true(x)
  134. assert is_true2(x)
  135. assert not is_false(x)
  136. def test_str_min_max() -> None:
  137. x: str = 'aaa'
  138. y: str = 'bbb'
  139. z: str = 'aa'
  140. assert min(x, y) == 'aaa'
  141. assert min(x, z) == 'aa'
  142. assert max(x, y) == 'bbb'
  143. assert max(x, z) == 'aaa'
  144. [case testStringFormattingCStyle]
  145. [typing fixtures/typing-full.pyi]
  146. from typing import Tuple
  147. var = 'mypyc'
  148. num = 20
  149. def test_basics() -> None:
  150. assert 'Hello %s, this is a test' % var == "Hello mypyc, this is a test"
  151. assert 'Hello %s %d, this is a test' % (var, num) == "Hello mypyc 20, this is a test"
  152. t: Tuple[str, int] = (var, num)
  153. assert 'Hello %s %d, this is a test' % t == "Hello mypyc 20, this is a test"
  154. large_num = 2**65
  155. assert 'number: %d' % large_num == 'number: 36893488147419103232'
  156. neg_num = -3
  157. assert 'negative integer: %d' % neg_num == 'negative integer: -3'
  158. assert 'negative integer: %d' % (-large_num) == 'negative integer: -36893488147419103232'
  159. bool_var1 = True
  160. bool_var2 = False
  161. assert 'bool: %s, %s' % (bool_var1, bool_var2) == 'bool: True, False'
  162. float_num = 123.4
  163. assert '%f' % float_num == '123.400000'
  164. assert '%.2f' % float_num == '123.40'
  165. assert '%.5f' % float_num == '123.40000'
  166. assert '%10.2f' % float_num == ' 123.40'
  167. assert '%10.5f' % float_num == ' 123.40000'
  168. assert '%010.5f' % float_num == '0123.40000'
  169. assert '%015.5f' % float_num == '000000123.40000'
  170. assert '%e' % float_num == '1.234000e+02'
  171. large_float = 1.23e30
  172. large_float2 = 1234123412341234123400000000000000000
  173. small_float = 1.23e-20
  174. assert '%f, %f, %f' % (small_float, large_float, large_float2) == \
  175. '0.000000, 1229999999999999959718843908096.000000, 1234123412341234169005079998930878464.000000'
  176. assert '%s, %s, %s' % (small_float, large_float, large_float2) == \
  177. '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
  178. assert '%d, %d, %d' % (small_float, large_float, large_float2) == \
  179. '0, 1229999999999999959718843908096, 1234123412341234123400000000000000000'
  180. nan_num = float('nan')
  181. inf_num = float('inf')
  182. assert '%s, %s' % (nan_num, inf_num) == 'nan, inf'
  183. assert '%f, %f' % (nan_num, inf_num) == 'nan, inf'
  184. [case testFStrings]
  185. import decimal
  186. from datetime import datetime
  187. var = 'mypyc'
  188. num = 20
  189. def test_fstring_basics() -> None:
  190. assert f'Hello {var}, this is a test' == "Hello mypyc, this is a test"
  191. large_num = 2**65
  192. assert f'number: {large_num}' == 'number: 36893488147419103232'
  193. neg_num = -3
  194. assert f'negative integer: {neg_num}' == 'negative integer: -3'
  195. assert f'negative integer: {-large_num}' == 'negative integer: -36893488147419103232'
  196. bool_var1 = True
  197. bool_var2 = False
  198. assert f'bool: {bool_var1}, {bool_var2}' == 'bool: True, False'
  199. x = bytes([1, 2, 3, 4])
  200. # assert f'bytes: {x}' == "bytes: b'\\x01\\x02\\x03\\x04'"
  201. # error: If x = b'abc' then f"{x}" or "{}".format(x) produces "b'abc'", not "abc". If this is desired behavior, use f"{x!r}" or "{!r}".format(x). Otherwise, decode the bytes
  202. float_num = 123.4
  203. assert f'{float_num}' == '123.4'
  204. assert f'{float_num:.2f}' == '123.40'
  205. assert f'{float_num:.5f}' == '123.40000'
  206. assert f'{float_num:>10.2f}' == ' 123.40'
  207. assert f'{float_num:>10.5f}' == ' 123.40000'
  208. assert f'{float_num:>010.5f}' == '0123.40000'
  209. assert f'{float_num:>015.5f}' == '000000123.40000'
  210. assert f'{float_num:e}' == '1.234000e+02'
  211. large_float = 1.23e30
  212. large_float2 = 1234123412341234123400000000000000000
  213. small_float = 1.23e-20
  214. assert f'{small_float}, {large_float}, {large_float2}' == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
  215. nan_num = float('nan')
  216. inf_num = float('inf')
  217. assert f'{nan_num}, {inf_num}' == 'nan, inf'
  218. # F-strings would be translated into ''.join[string literals, format method call, ...] in mypy AST.
  219. # Currently we are using a str.join specializer for f-string speed up. We might not cover all cases
  220. # and the rest ones should fall back to a normal str.join method call.
  221. # TODO: Once we have a new pipeline for f-strings, this test case can be moved to testStringOps.
  222. def test_str_join() -> None:
  223. var = 'mypyc'
  224. num = 10
  225. assert ''.join(['a', 'b', '{}'.format(var), 'c']) == 'abmypycc'
  226. assert ''.join(['a', 'b', '{:{}}'.format(var, ''), 'c']) == 'abmypycc'
  227. assert ''.join(['a', 'b', '{:{}}'.format(var, '>10'), 'c']) == 'ab mypycc'
  228. assert ''.join(['a', 'b', '{:{}}'.format(var, '>{}'.format(num)), 'c']) == 'ab mypycc'
  229. assert var.join(['a', '{:{}}'.format(var, ''), 'b']) == 'amypycmypycmypycb'
  230. assert ','.join(['a', '{:{}}'.format(var, ''), 'b']) == 'a,mypyc,b'
  231. assert ''.join(['x', var]) == 'xmypyc'
  232. class A:
  233. def __init__(self, name, age):
  234. self.name = name
  235. self.age = age
  236. def __repr__(self):
  237. return f'{self.name} is {self.age} years old.'
  238. def test_fstring_datatype() -> None:
  239. u = A('John Doe', 14)
  240. assert f'{u}' == 'John Doe is 14 years old.'
  241. d = {'name': 'John Doe', 'age': 14}
  242. assert f'{d}' == "{'name': 'John Doe', 'age': 14}"
  243. def test_fstring_escape() -> None:
  244. assert f"{'inside'}" == 'inside'
  245. assert f'{"inside"}' == 'inside'
  246. assert f"""inside""" == 'inside'
  247. assert f'''inside''' == 'inside'
  248. assert f"\"{'inside'}\"" == '"inside"'
  249. assert f'\'{"inside"}\'' == "'inside'"
  250. assert f'{{10}}' == '{10}'
  251. assert f'{{10 + 10}}' == '{10 + 10}'
  252. assert f'{{{10 + 10}}}' == '{20}'
  253. assert f'{{{{10 + 10}}}}' == '{{10 + 10}}'
  254. def test_fstring_conversion() -> None:
  255. assert f'Hello {var!r}' == "Hello 'mypyc'"
  256. # repr() is equivalent to !r
  257. assert f'Hello {repr(var)}' == "Hello 'mypyc'"
  258. assert f'Hello {var!a}' == "Hello 'mypyc'"
  259. # ascii() is equivalent to !a
  260. assert f'Hello {ascii(var)}' == "Hello 'mypyc'"
  261. tmp_str = """this
  262. is a new line."""
  263. assert f'Test: {tmp_str!a}' == "Test: 'this\\n is a new line.'"
  264. s = 'test: āĀēĒčČ..šŠūŪžŽ'
  265. assert f'{s}' == 'test: āĀēĒčČ..šŠūŪžŽ'
  266. assert f'{s!a}' == "'test: \\u0101\\u0100\\u0113\\u0112\\u010d\\u010c..\\u0161\\u0160\\u016b\\u016a\\u017e\\u017d'"
  267. assert f'Hello {var!s}' == 'Hello mypyc'
  268. assert f'Hello {num!s}' == 'Hello 20'
  269. def test_fstring_align() -> None:
  270. assert f'Hello {var:>20}' == "Hello mypyc"
  271. assert f'Hello {var!r:>20}' == "Hello 'mypyc'"
  272. assert f'Hello {var:>{num}}' == "Hello mypyc"
  273. assert f'Hello {var!r:>{num}}' == "Hello 'mypyc'"
  274. def test_fstring_multi() -> None:
  275. assert f'Hello {var}, hello again {var}' == "Hello mypyc, hello again mypyc"
  276. a = 'py'
  277. s = f'my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}my{a}'
  278. assert s == 'mypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypy'
  279. def test_fstring_python_doc() -> None:
  280. name = 'Fred'
  281. assert f"He said his name is {name!r}." == "He said his name is 'Fred'."
  282. assert f"He said his name is {repr(name)}." == "He said his name is 'Fred'."
  283. width = 10
  284. precision = 4
  285. value = decimal.Decimal('12.34567')
  286. assert f'result: {value:{width}.{precision}}' == 'result: 12.35' # nested field
  287. today = datetime(year=2017, month=1, day=27)
  288. assert f'{today:%B %d, %Y}' == 'January 27, 2017' # using date format specifier
  289. number = 1024
  290. assert f'{number:#0x}' == '0x400' # using integer format specifier
  291. [case testStringFormatMethod]
  292. from typing import Tuple
  293. def test_format_method_basics() -> None:
  294. x = str()
  295. assert 'x{}'.format(x) == 'x'
  296. assert 'ā{}'.format(x) == 'ā'
  297. assert '😀{}'.format(x) == '😀'
  298. assert ''.format() == ''
  299. assert 'abc'.format() == 'abc'
  300. assert '{}{}'.format(1, 2) == '12'
  301. name = 'Eric'
  302. age = 14
  303. assert "My name is {name}, I'm {age}.".format(name=name, age=age) == "My name is Eric, I'm 14."
  304. assert "My name is {A}, I'm {B}.".format(A=name, B=age) == "My name is Eric, I'm 14."
  305. assert "My name is {}, I'm {B}.".format(name, B=age) == "My name is Eric, I'm 14."
  306. bool_var1 = True
  307. bool_var2 = False
  308. assert 'bool: {}, {}'.format(bool_var1, bool_var2) == 'bool: True, False'
  309. def test_format_method_empty_braces() -> None:
  310. name = 'Eric'
  311. age = 14
  312. assert 'Hello, {}!'.format(name) == 'Hello, Eric!'
  313. assert '{}'.format(name) == 'Eric'
  314. assert '{}! Hi!'.format(name) == 'Eric! Hi!'
  315. assert '{}, Hi, {}'.format(name, name) == 'Eric, Hi, Eric'
  316. assert 'Hi! {}'.format(name) == 'Hi! Eric'
  317. assert "Hi, I'm {}. I'm {}.".format(name, age) == "Hi, I'm Eric. I'm 14."
  318. assert '{{}}'.format() == '{}'
  319. assert '{{{{}}}}'.format() == '{{}}'
  320. assert '{{}}{}'.format(name) == '{}Eric'
  321. assert 'Hi! {{{}}}'.format(name) == 'Hi! {Eric}'
  322. assert 'Hi! {{ {}'.format(name) == 'Hi! { Eric'
  323. assert 'Hi! {{ {} }}}}'.format(name) == 'Hi! { Eric }}'
  324. def test_format_method_numbers() -> None:
  325. s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-233)
  326. assert s == 'int: -233; hex: -e9; oct: -351; bin: -11101001'
  327. num = 2**65
  328. s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(num)
  329. assert s == 'int: 36893488147419103232; hex: 20000000000000000; oct: 4000000000000000000000; bin: 100000000000000000000000000000000000000000000000000000000000000000'
  330. s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-num)
  331. assert s == 'int: -36893488147419103232; hex: -20000000000000000; oct: -4000000000000000000000; bin: -100000000000000000000000000000000000000000000000000000000000000000'
  332. large_num = 2**65
  333. assert 'number: {}'.format(large_num) == 'number: 36893488147419103232'
  334. neg_num = -3
  335. assert 'negative integer: {}'.format(neg_num) == 'negative integer: -3'
  336. assert 'negative integer: {}'.format(-large_num) == 'negative integer: -36893488147419103232'
  337. large_float = 1.23e30
  338. large_float2 = 1234123412341234123400000000000000000
  339. small_float = 1.23e-20
  340. assert '{}, {}, {}'.format(small_float, large_float, large_float2) == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000'
  341. nan_num = float('nan')
  342. inf_num = float('inf')
  343. assert '{}, {}'.format(nan_num, inf_num) == 'nan, inf'
  344. def format_args(*args: int) -> str:
  345. return 'x{}y{}'.format(*args)
  346. def format_kwargs(**kwargs: int) -> str:
  347. return 'c{x}d{y}'.format(**kwargs)
  348. def format_args_self(*args: int) -> str:
  349. return '{}'.format(args)
  350. def format_kwargs_self(**kwargs: int) -> str:
  351. return '{}'.format(kwargs)
  352. def test_format_method_args() -> None:
  353. assert format_args(10, 2) == 'x10y2'
  354. assert format_args_self(10, 2) == '(10, 2)'
  355. assert format_kwargs(x=10, y=2) == 'c10d2'
  356. assert format_kwargs(x=10, y=2, z=1) == 'c10d2'
  357. assert format_kwargs_self(x=10, y=2, z=1) == "{'x': 10, 'y': 2, 'z': 1}"
  358. def test_format_method_different_kind() -> None:
  359. s1 = "Literal['😀']"
  360. assert 'Revealed type is {}'.format(s1) == "Revealed type is Literal['😀']"
  361. s2 = "Revealed type is"
  362. assert "{} Literal['😀']".format(s2) == "Revealed type is Literal['😀']"
  363. s3 = "测试:"
  364. assert "{}{} {}".format(s3, s2, s1) == "测试:Revealed type is Literal['😀']"
  365. assert "Test: {}{}".format(s3, s1) == "Test: 测试:Literal['😀']"
  366. assert "Test: {}{}".format(s3, s2) == "Test: 测试:Revealed type is"
  367. def test_format_method_nested() -> None:
  368. var = 'mypyc'
  369. num = 10
  370. assert '{:{}}'.format(var, '') == 'mypyc'
  371. assert '{:{}}'.format(var, '>10') == ' mypyc'
  372. assert '{:{}}'.format(var, '>{}'.format(num)) == ' mypyc'
  373. class Point:
  374. def __init__(self, x, y):
  375. self.x, self.y = x, y
  376. def __str__(self):
  377. return 'Point({self.x}, {self.y})'.format(self=self)
  378. # Format examples from Python doc
  379. # https://docs.python.org/3/library/string.html#formatexamples
  380. def test_format_method_python_doc() -> None:
  381. # Accessing arguments by position:
  382. assert '{0}, {1}, {2}'.format('a', 'b', 'c') == 'a, b, c'
  383. assert '{}, {}, {}'.format('a', 'b', 'c') == 'a, b, c'
  384. assert '{2}, {1}, {0}'.format('a', 'b', 'c') == 'c, b, a'
  385. assert '{2}, {1}, {0}'.format(*'abc') == 'c, b, a' # unpacking argument sequence
  386. # assert '{0}{1}{0}'.format('abra', 'cad') = 'abracadabra' # arguments' indices can be repeated
  387. # Accessing arguments by name:
  388. s = 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
  389. assert s == 'Coordinates: 37.24N, -115.81W'
  390. coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
  391. assert 'Coordinates: {latitude}, {longitude}'.format(**coord) == 'Coordinates: 37.24N, -115.81W'
  392. # Accessing arguments’ attributes:
  393. assert str(Point(4, 2)) == 'Point(4, 2)'
  394. # Accessing arguments’ items:
  395. coord2 = (3, 5)
  396. assert 'X: {0[0]}; Y: {0[1]}'.format(coord2) == 'X: 3; Y: 5'
  397. # Replacing %s and %r:
  398. s = "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
  399. assert s == "repr() shows quotes: 'test1'; str() doesn't: test2"
  400. # Aligning the text and specifying a width:
  401. assert '{:<30}'.format('left aligned') == 'left aligned '
  402. assert '{:>30}'.format('right aligned') == ' right aligned'
  403. assert '{:^30}'.format('centered') == ' centered '
  404. assert '{:*^30}'.format('centered') == '***********centered***********' # use '*' as a fill char
  405. # Replacing %+f, %-f, and % f and specifying a sign:
  406. assert '{:+f}; {:+f}'.format(3.14, -3.14) == '+3.140000; -3.140000' # show it always
  407. assert '{: f}; {: f}'.format(3.14, -3.14) == ' 3.140000; -3.140000' # show a space for positive numbers
  408. assert '{:-f}; {:-f}'.format(3.14, -3.14) == '3.140000; -3.140000' # show only the minus -- same as '{:f}; {:f}'
  409. # Replacing %x and %o and converting the value to different bases:
  410. s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(42) # format also supports binary numbers
  411. assert s == 'int: 42; hex: 2a; oct: 52; bin: 101010'
  412. s = 'int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}'.format(42) # with 0x, 0o, or 0b as prefix:
  413. assert s == 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
  414. # Using the comma as a thousands separator:
  415. assert '{:,}'.format(1234567890) == '1,234,567,890'
  416. # Expressing a percentage:
  417. points = 19.0
  418. total = 22.0
  419. assert 'Correct answers: {:.2%}'.format(points/total) == 'Correct answers: 86.36%'
  420. # Using type-specific formatting:
  421. import datetime
  422. d = datetime.datetime(2010, 7, 4, 12, 15, 58)
  423. assert '{:%Y-%m-%d %H:%M:%S}'.format(d) == '2010-07-04 12:15:58'
  424. # Nesting arguments and more complex examples:
  425. tmp_strs = []
  426. for align, text in zip('<^>', ['left', 'center', 'right']):
  427. tmp_strs.append('{0:{fill}{align}16}'.format(text, fill=align, align=align))
  428. assert tmp_strs == ['left<<<<<<<<<<<<', '^^^^^center^^^^^', '>>>>>>>>>>>right']
  429. octets = [192, 168, 0, 1]
  430. assert '{:02X}{:02X}{:02X}{:02X}'.format(*octets) == 'C0A80001'
  431. width = 5
  432. tmp_strs = []
  433. for num in range(5,12):
  434. tmp_str = ''
  435. for base in 'dXob':
  436. tmp_str += ('{0:{width}{base}}'.format(num, base=base, width=width))
  437. tmp_strs.append(tmp_str)
  438. assert tmp_strs == [' 5 5 5 101',\
  439. ' 6 6 6 110',\
  440. ' 7 7 7 111',\
  441. ' 8 8 10 1000',\
  442. ' 9 9 11 1001',\
  443. ' 10 A 12 1010',\
  444. ' 11 B 13 1011']
  445. [case testChr]
  446. # Some test cases are from https://docs.python.org/3/howto/unicode.html
  447. def try_invalid(x: int) -> bool:
  448. try:
  449. chr(x + int())
  450. return False
  451. except ValueError:
  452. return True
  453. def test_chr() -> None:
  454. assert chr(57344) == '\ue000'
  455. assert chr(0) == '\x00'
  456. assert chr(65) == 'A'
  457. assert chr(150) == '\x96'
  458. try:
  459. chr(-1)
  460. assert False
  461. except ValueError:
  462. pass
  463. try:
  464. chr(1114112)
  465. assert False
  466. except ValueError:
  467. pass
  468. assert chr(1114111) == '\U0010ffff'
  469. x = 0
  470. assert chr(x + int()) == '\x00'
  471. x = 100
  472. assert chr(x + int()) == 'd'
  473. x = 150
  474. assert chr(x + int()) == '\x96'
  475. x = 257
  476. assert chr(x + int()) == 'ā'
  477. x = 65537
  478. assert chr(x + int()) == '𐀁'
  479. assert try_invalid(-1)
  480. assert try_invalid(1114112)
  481. [case testOrd]
  482. def test_ord() -> None:
  483. assert ord('\ue000') == 57344
  484. s = "a\xac\u1234\u20ac\U00008000"
  485. # ^^^^ two-digit hex escape
  486. # ^^^^^^ four-digit Unicode escape
  487. # ^^^^^^^^^^ eight-digit Unicode escape
  488. l1 = [ord(c) for c in s]
  489. assert l1 == [97, 172, 4660, 8364, 32768]
  490. u = 'abcdé'
  491. assert ord(u[-1]) == 233
  492. assert ord(b'a') == 97
  493. assert ord(b'a' + bytes()) == 97
  494. u2 = '\U0010ffff'
  495. assert ord(u2) == 1114111
  496. try:
  497. ord('aa')
  498. assert False
  499. except TypeError:
  500. pass
  501. [case testDecode]
  502. def test_decode() -> None:
  503. assert "\N{GREEK CAPITAL LETTER DELTA}" == '\u0394'
  504. assert "\u0394" == "\u0394"
  505. assert "\U00000394" == '\u0394'
  506. assert b'\x80abc'.decode('utf-8', 'replace') == '\ufffdabc'
  507. assert b'\x80abc'.decode('utf-8', 'backslashreplace') == '\\x80abc'
  508. assert b'abc'.decode() == 'abc'
  509. assert b'abc'.decode('utf-8') == 'abc'
  510. assert b'\x80abc'.decode('utf-8', 'ignore') == 'abc'
  511. assert b'\x80abc'.decode('UTF-8', 'ignore') == 'abc'
  512. assert b'\x80abc'.decode('Utf-8', 'ignore') == 'abc'
  513. assert b'\x80abc'.decode('utf_8', 'ignore') == 'abc'
  514. assert b'\x80abc'.decode('latin1', 'ignore') == '\x80abc'
  515. assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('gbk', 'ignore') == '一二三'
  516. assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('latin1', 'ignore') == 'Ò»¶þÈý'
  517. assert b'Z\xc3\xbcrich'.decode("utf-8") == 'Zürich'
  518. try:
  519. b'Z\xc3\xbcrich'.decode('ascii')
  520. assert False
  521. except UnicodeDecodeError:
  522. pass
  523. assert bytearray(range(5)).decode() == '\x00\x01\x02\x03\x04'
  524. b = bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd')
  525. assert b.decode() == '你好'
  526. assert b.decode('gbk') == '浣犲ソ'
  527. assert b.decode('latin1') == 'ä½\xa0好'
  528. [case testEncode]
  529. from testutil import assertRaises
  530. def test_encode() -> None:
  531. u = chr(40960) + 'abcd' + chr(1972)
  532. assert u.encode() == b'\xea\x80\x80abcd\xde\xb4'
  533. assert u.encode('utf-8') == b'\xea\x80\x80abcd\xde\xb4'
  534. with assertRaises(UnicodeEncodeError):
  535. u.encode('ascii')
  536. with assertRaises(LookupError):
  537. u.encode('aaa')
  538. assert u.encode('utf-8', 'aaaaaa') == b'\xea\x80\x80abcd\xde\xb4'
  539. assert u.encode('ascii', 'ignore') == b'abcd'
  540. assert u.encode('ASCII', 'ignore') == b'abcd'
  541. assert u.encode('ascii', 'replace') == b'?abcd?'
  542. assert u.encode('ascii', 'xmlcharrefreplace') == b'&#40960;abcd&#1972;'
  543. assert u.encode('ascii', 'backslashreplace') == b'\\ua000abcd\\u07b4'
  544. assert u.encode('ascii', 'namereplace') == b'\\N{YI SYLLABLE IT}abcd\\u07b4'
  545. assert 'pythön!'.encode() == b'pyth\xc3\xb6n!'
  546. assert '一二三'.encode('gbk') == b'\xd2\xbb\xb6\xfe\xc8\xfd'
  547. assert u.encode('UTF-8', 'ignore') == b'\xea\x80\x80abcd\xde\xb4'
  548. assert u.encode('Utf_8') == b'\xea\x80\x80abcd\xde\xb4'
  549. assert u.encode('UTF_8') == b'\xea\x80\x80abcd\xde\xb4'
  550. assert u'\u00E1'.encode('latin1') == b'\xe1'
  551. with assertRaises(UnicodeEncodeError):
  552. u.encode('latin1')