| # Test cases for strings (compile and run) |
| |
| [case testStrBasics] |
| from typing import Tuple |
| def f() -> str: |
| return 'some string' |
| def g() -> str: |
| return 'some\a \v \t \x7f " \n \0string 🐍' |
| def tostr(x: int) -> str: |
| return str(x) |
| def booltostr(x: bool) -> str: |
| return str(x) |
| def concat(x: str, y: str) -> str: |
| return x + y |
| def eq(x: str) -> int: |
| if x == 'foo': |
| return 0 |
| elif x != 'bar': |
| return 1 |
| return 2 |
| def match(x: str, y: str) -> Tuple[bool, bool]: |
| return (x.startswith(y), x.endswith(y)) |
| |
| [file driver.py] |
| from native import f, g, tostr, booltostr, concat, eq, match |
| import sys |
| |
| assert f() == 'some string' |
| assert f() is sys.intern('some string') |
| assert g() == 'some\a \v \t \x7f " \n \0string 🐍' |
| assert tostr(57) == '57' |
| assert concat('foo', 'bar') == 'foobar' |
| assert booltostr(True) == 'True' |
| assert booltostr(False) == 'False' |
| assert eq('foo') == 0 |
| assert eq('zar') == 1 |
| assert eq('bar') == 2 |
| |
| assert int(tostr(0)) == 0 |
| assert int(tostr(20)) == 20 |
| assert match('', '') == (True, True) |
| assert match('abc', '') == (True, True) |
| assert match('abc', 'a') == (True, False) |
| assert match('abc', 'c') == (False, True) |
| assert match('', 'abc') == (False, False) |
| |
| [case testStringOps] |
| from typing import List, Optional |
| |
| def do_split(s: str, sep: Optional[str] = None, max_split: Optional[int] = None) -> List[str]: |
| if sep is not None: |
| if max_split is not None: |
| return s.split(sep, max_split) |
| else: |
| return s.split(sep) |
| return s.split() |
| |
| ss = "abc abcd abcde abcdef" |
| |
| def test_split() -> None: |
| assert do_split(ss) == ["abc", "abcd", "abcde", "abcdef"] |
| assert do_split(ss, " ") == ["abc", "abcd", "abcde", "abcdef"] |
| assert do_split(ss, "-") == ["abc abcd abcde abcdef"] |
| assert do_split(ss, " ", -1) == ["abc", "abcd", "abcde", "abcdef"] |
| assert do_split(ss, " ", 0) == ["abc abcd abcde abcdef"] |
| assert do_split(ss, " ", 1) == ["abc", "abcd abcde abcdef"] |
| assert do_split(ss, " ", 2) == ["abc", "abcd", "abcde abcdef"] |
| |
| def getitem(s: str, index: int) -> str: |
| return s[index] |
| |
| from testutil import assertRaises |
| |
| s = "abc" |
| |
| def test_getitem() -> None: |
| assert getitem(s, 0) == "a" |
| assert getitem(s, 1) == "b" |
| assert getitem(s, 2) == "c" |
| assert getitem(s, -3) == "a" |
| assert getitem(s, -2) == "b" |
| assert getitem(s, -1) == "c" |
| with assertRaises(IndexError, "string index out of range"): |
| getitem(s, 4) |
| with assertRaises(IndexError, "string index out of range"): |
| getitem(s, -4) |
| |
| def str_to_int(s: str, base: Optional[int] = None) -> int: |
| if base: |
| return int(s, base) |
| else: |
| return int(s) |
| |
| def test_str_to_int() -> None: |
| assert str_to_int("1") == 1 |
| assert str_to_int("10") == 10 |
| assert str_to_int("a", 16) == 10 |
| assert str_to_int("1a", 16) == 26 |
| with assertRaises(ValueError, "invalid literal for int() with base 10: 'xyz'"): |
| str_to_int("xyz") |
| |
| def test_slicing() -> None: |
| # Use dummy adds to avoid constant folding |
| zero = int() |
| two = zero + 2 |
| s = "foobar" + str() |
| assert s[two:] == "obar" |
| assert s[:two] == "fo" |
| assert s[two:-two] == "ob" |
| assert s[two:two] == "" |
| assert s[two:two + 1] == "o" |
| assert s[-two:] == "ar" |
| assert s[:-two] == "foob" |
| assert s[:] == "foobar" |
| assert s[two:333] == "obar" |
| assert s[333:two] == "" |
| assert s[two:-333] == "" |
| assert s[-333:two] == "fo" |
| big_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 |
| assert s[1:big_int] == "oobar" |
| assert s[big_int:] == "" |
| assert s[-big_int:-1] == "fooba" |
| |
| def test_str_replace() -> None: |
| a = "foofoofoo" |
| assert a.replace("foo", "bar") == "barbarbar" |
| assert a.replace("foo", "bar", -1) == "barbarbar" |
| assert a.replace("foo", "bar", 1) == "barfoofoo" |
| assert a.replace("foo", "bar", 4) == "barbarbar" |
| assert a.replace("aaa", "bar") == "foofoofoo" |
| assert a.replace("ofo", "xyzw") == "foxyzwxyzwo" |
| |
| def is_true(x: str) -> bool: |
| if x: |
| return True |
| else: |
| return False |
| |
| def is_true2(x: str) -> bool: |
| return bool(x) |
| |
| def is_false(x: str) -> bool: |
| if not x: |
| return True |
| else: |
| return False |
| |
| def test_str_to_bool() -> None: |
| assert is_false('') |
| assert not is_true('') |
| assert not is_true2('') |
| for x in 'a', 'foo', 'bar', 'some string': |
| assert is_true(x) |
| assert is_true2(x) |
| assert not is_false(x) |
| |
| def test_str_min_max() -> None: |
| x: str = 'aaa' |
| y: str = 'bbb' |
| z: str = 'aa' |
| assert min(x, y) == 'aaa' |
| assert min(x, z) == 'aa' |
| assert max(x, y) == 'bbb' |
| assert max(x, z) == 'aaa' |
| |
| [case testStringFormattingCStyle] |
| [typing fixtures/typing-full.pyi] |
| from typing import Tuple |
| |
| var = 'mypyc' |
| num = 20 |
| |
| def test_basics() -> None: |
| assert 'Hello %s, this is a test' % var == "Hello mypyc, this is a test" |
| assert 'Hello %s %d, this is a test' % (var, num) == "Hello mypyc 20, this is a test" |
| t: Tuple[str, int] = (var, num) |
| assert 'Hello %s %d, this is a test' % t == "Hello mypyc 20, this is a test" |
| |
| large_num = 2**65 |
| assert 'number: %d' % large_num == 'number: 36893488147419103232' |
| neg_num = -3 |
| assert 'negative integer: %d' % neg_num == 'negative integer: -3' |
| assert 'negative integer: %d' % (-large_num) == 'negative integer: -36893488147419103232' |
| |
| bool_var1 = True |
| bool_var2 = False |
| assert 'bool: %s, %s' % (bool_var1, bool_var2) == 'bool: True, False' |
| |
| float_num = 123.4 |
| assert '%f' % float_num == '123.400000' |
| assert '%.2f' % float_num == '123.40' |
| assert '%.5f' % float_num == '123.40000' |
| assert '%10.2f' % float_num == ' 123.40' |
| assert '%10.5f' % float_num == ' 123.40000' |
| assert '%010.5f' % float_num == '0123.40000' |
| assert '%015.5f' % float_num == '000000123.40000' |
| assert '%e' % float_num == '1.234000e+02' |
| large_float = 1.23e30 |
| large_float2 = 1234123412341234123400000000000000000 |
| small_float = 1.23e-20 |
| assert '%f, %f, %f' % (small_float, large_float, large_float2) == \ |
| '0.000000, 1229999999999999959718843908096.000000, 1234123412341234169005079998930878464.000000' |
| assert '%s, %s, %s' % (small_float, large_float, large_float2) == \ |
| '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000' |
| assert '%d, %d, %d' % (small_float, large_float, large_float2) == \ |
| '0, 1229999999999999959718843908096, 1234123412341234123400000000000000000' |
| |
| nan_num = float('nan') |
| inf_num = float('inf') |
| assert '%s, %s' % (nan_num, inf_num) == 'nan, inf' |
| assert '%f, %f' % (nan_num, inf_num) == 'nan, inf' |
| |
| [case testFStrings] |
| import decimal |
| from datetime import datetime |
| |
| var = 'mypyc' |
| num = 20 |
| |
| def test_fstring_basics() -> None: |
| assert f'Hello {var}, this is a test' == "Hello mypyc, this is a test" |
| |
| large_num = 2**65 |
| assert f'number: {large_num}' == 'number: 36893488147419103232' |
| neg_num = -3 |
| assert f'negative integer: {neg_num}' == 'negative integer: -3' |
| assert f'negative integer: {-large_num}' == 'negative integer: -36893488147419103232' |
| |
| bool_var1 = True |
| bool_var2 = False |
| assert f'bool: {bool_var1}, {bool_var2}' == 'bool: True, False' |
| |
| x = bytes([1, 2, 3, 4]) |
| |
| float_num = 123.4 |
| assert f'{float_num}' == '123.4' |
| assert f'{float_num:.2f}' == '123.40' |
| assert f'{float_num:.5f}' == '123.40000' |
| assert f'{float_num:>10.2f}' == ' 123.40' |
| assert f'{float_num:>10.5f}' == ' 123.40000' |
| assert f'{float_num:>010.5f}' == '0123.40000' |
| assert f'{float_num:>015.5f}' == '000000123.40000' |
| assert f'{float_num:e}' == '1.234000e+02' |
| |
| large_float = 1.23e30 |
| large_float2 = 1234123412341234123400000000000000000 |
| small_float = 1.23e-20 |
| assert f'{small_float}, {large_float}, {large_float2}' == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000' |
| nan_num = float('nan') |
| inf_num = float('inf') |
| assert f'{nan_num}, {inf_num}' == 'nan, inf' |
| |
| # F-strings would be translated into ''.join[string literals, format method call, ...] in mypy AST. |
| # Currently we are using a str.join specializer for f-string speed up. We might not cover all cases |
| # and the rest ones should fall back to a normal str.join method call. |
| # TODO: Once we have a new pipeline for f-strings, this test case can be moved to testStringOps. |
| def test_str_join() -> None: |
| var = 'mypyc' |
| num = 10 |
| assert ''.join(['a', 'b', '{}'.format(var), 'c']) == 'abmypycc' |
| assert ''.join(['a', 'b', '{:{}}'.format(var, ''), 'c']) == 'abmypycc' |
| assert ''.join(['a', 'b', '{:{}}'.format(var, '>10'), 'c']) == 'ab mypycc' |
| assert ''.join(['a', 'b', '{:{}}'.format(var, '>{}'.format(num)), 'c']) == 'ab mypycc' |
| assert var.join(['a', '{:{}}'.format(var, ''), 'b']) == 'amypycmypycmypycb' |
| assert ','.join(['a', '{:{}}'.format(var, ''), 'b']) == 'a,mypyc,b' |
| assert ''.join(['x', var]) == 'xmypyc' |
| |
| class A: |
| def __init__(self, name, age): |
| self.name = name |
| self.age = age |
| |
| def __repr__(self): |
| return f'{self.name} is {self.age} years old.' |
| |
| def test_fstring_datatype() -> None: |
| u = A('John Doe', 14) |
| assert f'{u}' == 'John Doe is 14 years old.' |
| d = {'name': 'John Doe', 'age': 14} |
| assert f'{d}' == "{'name': 'John Doe', 'age': 14}" |
| |
| def test_fstring_escape() -> None: |
| assert f"{'inside'}" == 'inside' |
| assert f'{"inside"}' == 'inside' |
| assert f"""inside""" == 'inside' |
| assert f'''inside''' == 'inside' |
| assert f"\"{'inside'}\"" == '"inside"' |
| assert f'\'{"inside"}\'' == "'inside'" |
| |
| assert f'{{10}}' == '{10}' |
| assert f'{{10 + 10}}' == '{10 + 10}' |
| assert f'{{{10 + 10}}}' == '{20}' |
| assert f'{{{{10 + 10}}}}' == '{{10 + 10}}' |
| |
| def test_fstring_conversion() -> None: |
| assert f'Hello {var!r}' == "Hello 'mypyc'" |
| # repr() is equivalent to !r |
| assert f'Hello {repr(var)}' == "Hello 'mypyc'" |
| |
| assert f'Hello {var!a}' == "Hello 'mypyc'" |
| # ascii() is equivalent to !a |
| assert f'Hello {ascii(var)}' == "Hello 'mypyc'" |
| |
| tmp_str = """this |
| is a new line.""" |
| assert f'Test: {tmp_str!a}' == "Test: 'this\\n is a new line.'" |
| |
| s = 'test: āĀēĒčČ..šŠūŪžŽ' |
| assert f'{s}' == 'test: āĀēĒčČ..šŠūŪžŽ' |
| assert f'{s!a}' == "'test: \\u0101\\u0100\\u0113\\u0112\\u010d\\u010c..\\u0161\\u0160\\u016b\\u016a\\u017e\\u017d'" |
| |
| assert f'Hello {var!s}' == 'Hello mypyc' |
| assert f'Hello {num!s}' == 'Hello 20' |
| |
| def test_fstring_align() -> None: |
| assert f'Hello {var:>20}' == "Hello mypyc" |
| assert f'Hello {var!r:>20}' == "Hello 'mypyc'" |
| assert f'Hello {var:>{num}}' == "Hello mypyc" |
| assert f'Hello {var!r:>{num}}' == "Hello 'mypyc'" |
| |
| def test_fstring_multi() -> None: |
| assert f'Hello {var}, hello again {var}' == "Hello mypyc, hello again mypyc" |
| a = 'py' |
| 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}' |
| assert s == 'mypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypymypy' |
| |
| def test_fstring_python_doc() -> None: |
| name = 'Fred' |
| assert f"He said his name is {name!r}." == "He said his name is 'Fred'." |
| assert f"He said his name is {repr(name)}." == "He said his name is 'Fred'." |
| |
| width = 10 |
| precision = 4 |
| value = decimal.Decimal('12.34567') |
| assert f'result: {value:{width}.{precision}}' == 'result: 12.35' # nested field |
| |
| today = datetime(year=2017, month=1, day=27) |
| assert f'{today:%B %d, %Y}' == 'January 27, 2017' # using date format specifier |
| |
| number = 1024 |
| assert f'{number:#0x}' == '0x400' # using integer format specifier |
| |
| [case testStringFormatMethod] |
| from typing import Tuple |
| |
| def test_format_method_basics() -> None: |
| x = str() |
| assert 'x{}'.format(x) == 'x' |
| assert 'ā{}'.format(x) == 'ā' |
| assert '😀{}'.format(x) == '😀' |
| assert ''.format() == '' |
| assert 'abc'.format() == 'abc' |
| assert '{}{}'.format(1, 2) == '12' |
| |
| name = 'Eric' |
| age = 14 |
| assert "My name is {name}, I'm {age}.".format(name=name, age=age) == "My name is Eric, I'm 14." |
| assert "My name is {A}, I'm {B}.".format(A=name, B=age) == "My name is Eric, I'm 14." |
| assert "My name is {}, I'm {B}.".format(name, B=age) == "My name is Eric, I'm 14." |
| |
| bool_var1 = True |
| bool_var2 = False |
| assert 'bool: {}, {}'.format(bool_var1, bool_var2) == 'bool: True, False' |
| |
| def test_format_method_empty_braces() -> None: |
| name = 'Eric' |
| age = 14 |
| |
| assert 'Hello, {}!'.format(name) == 'Hello, Eric!' |
| assert '{}'.format(name) == 'Eric' |
| assert '{}! Hi!'.format(name) == 'Eric! Hi!' |
| assert '{}, Hi, {}'.format(name, name) == 'Eric, Hi, Eric' |
| assert 'Hi! {}'.format(name) == 'Hi! Eric' |
| assert "Hi, I'm {}. I'm {}.".format(name, age) == "Hi, I'm Eric. I'm 14." |
| |
| assert '{{}}'.format() == '{}' |
| assert '{{{{}}}}'.format() == '{{}}' |
| assert '{{}}{}'.format(name) == '{}Eric' |
| assert 'Hi! {{{}}}'.format(name) == 'Hi! {Eric}' |
| assert 'Hi! {{ {}'.format(name) == 'Hi! { Eric' |
| assert 'Hi! {{ {} }}}}'.format(name) == 'Hi! { Eric }}' |
| |
| def test_format_method_numbers() -> None: |
| s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-233) |
| assert s == 'int: -233; hex: -e9; oct: -351; bin: -11101001' |
| num = 2**65 |
| s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(num) |
| assert s == 'int: 36893488147419103232; hex: 20000000000000000; oct: 4000000000000000000000; bin: 100000000000000000000000000000000000000000000000000000000000000000' |
| s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(-num) |
| assert s == 'int: -36893488147419103232; hex: -20000000000000000; oct: -4000000000000000000000; bin: -100000000000000000000000000000000000000000000000000000000000000000' |
| |
| large_num = 2**65 |
| assert 'number: {}'.format(large_num) == 'number: 36893488147419103232' |
| neg_num = -3 |
| assert 'negative integer: {}'.format(neg_num) == 'negative integer: -3' |
| assert 'negative integer: {}'.format(-large_num) == 'negative integer: -36893488147419103232' |
| |
| large_float = 1.23e30 |
| large_float2 = 1234123412341234123400000000000000000 |
| small_float = 1.23e-20 |
| assert '{}, {}, {}'.format(small_float, large_float, large_float2) == '1.23e-20, 1.23e+30, 1234123412341234123400000000000000000' |
| nan_num = float('nan') |
| inf_num = float('inf') |
| assert '{}, {}'.format(nan_num, inf_num) == 'nan, inf' |
| |
| def format_args(*args: int) -> str: |
| return 'x{}y{}'.format(*args) |
| def format_kwargs(**kwargs: int) -> str: |
| return 'c{x}d{y}'.format(**kwargs) |
| def format_args_self(*args: int) -> str: |
| return '{}'.format(args) |
| def format_kwargs_self(**kwargs: int) -> str: |
| return '{}'.format(kwargs) |
| |
| def test_format_method_args() -> None: |
| assert format_args(10, 2) == 'x10y2' |
| assert format_args_self(10, 2) == '(10, 2)' |
| assert format_kwargs(x=10, y=2) == 'c10d2' |
| assert format_kwargs(x=10, y=2, z=1) == 'c10d2' |
| assert format_kwargs_self(x=10, y=2, z=1) == "{'x': 10, 'y': 2, 'z': 1}" |
| |
| def test_format_method_different_kind() -> None: |
| s1 = "Literal['😀']" |
| assert 'Revealed type is {}'.format(s1) == "Revealed type is Literal['😀']" |
| s2 = "Revealed type is" |
| assert "{} Literal['😀']".format(s2) == "Revealed type is Literal['😀']" |
| s3 = "测试:" |
| assert "{}{} {}".format(s3, s2, s1) == "测试:Revealed type is Literal['😀']" |
| assert "Test: {}{}".format(s3, s1) == "Test: 测试:Literal['😀']" |
| assert "Test: {}{}".format(s3, s2) == "Test: 测试:Revealed type is" |
| |
| def test_format_method_nested() -> None: |
| var = 'mypyc' |
| num = 10 |
| assert '{:{}}'.format(var, '') == 'mypyc' |
| assert '{:{}}'.format(var, '>10') == ' mypyc' |
| assert '{:{}}'.format(var, '>{}'.format(num)) == ' mypyc' |
| |
| class Point: |
| def __init__(self, x, y): |
| self.x, self.y = x, y |
| def __str__(self): |
| return 'Point({self.x}, {self.y})'.format(self=self) |
| |
| # Format examples from Python doc |
| # https://docs.python.org/3/library/string.html#formatexamples |
| def test_format_method_python_doc() -> None: |
| # Accessing arguments by position: |
| assert '{0}, {1}, {2}'.format('a', 'b', 'c') == 'a, b, c' |
| assert '{}, {}, {}'.format('a', 'b', 'c') == 'a, b, c' |
| assert '{2}, {1}, {0}'.format('a', 'b', 'c') == 'c, b, a' |
| assert '{2}, {1}, {0}'.format(*'abc') == 'c, b, a' # unpacking argument sequence |
| # assert '{0}{1}{0}'.format('abra', 'cad') = 'abracadabra' # arguments' indices can be repeated |
| |
| # Accessing arguments by name: |
| s = 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W') |
| assert s == 'Coordinates: 37.24N, -115.81W' |
| coord = {'latitude': '37.24N', 'longitude': '-115.81W'} |
| assert 'Coordinates: {latitude}, {longitude}'.format(**coord) == 'Coordinates: 37.24N, -115.81W' |
| |
| # Accessing arguments’ attributes: |
| assert str(Point(4, 2)) == 'Point(4, 2)' |
| |
| # Accessing arguments’ items: |
| coord2 = (3, 5) |
| assert 'X: {0[0]}; Y: {0[1]}'.format(coord2) == 'X: 3; Y: 5' |
| |
| # Replacing %s and %r: |
| s = "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2') |
| assert s == "repr() shows quotes: 'test1'; str() doesn't: test2" |
| |
| # Aligning the text and specifying a width: |
| assert '{:<30}'.format('left aligned') == 'left aligned ' |
| assert '{:>30}'.format('right aligned') == ' right aligned' |
| assert '{:^30}'.format('centered') == ' centered ' |
| assert '{:*^30}'.format('centered') == '***********centered***********' # use '*' as a fill char |
| |
| # Replacing %+f, %-f, and % f and specifying a sign: |
| assert '{:+f}; {:+f}'.format(3.14, -3.14) == '+3.140000; -3.140000' # show it always |
| assert '{: f}; {: f}'.format(3.14, -3.14) == ' 3.140000; -3.140000' # show a space for positive numbers |
| assert '{:-f}; {:-f}'.format(3.14, -3.14) == '3.140000; -3.140000' # show only the minus -- same as '{:f}; {:f}' |
| |
| # Replacing %x and %o and converting the value to different bases: |
| s = 'int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(42) # format also supports binary numbers |
| assert s == 'int: 42; hex: 2a; oct: 52; bin: 101010' |
| s = 'int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}'.format(42) # with 0x, 0o, or 0b as prefix: |
| assert s == 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010' |
| |
| # Using the comma as a thousands separator: |
| assert '{:,}'.format(1234567890) == '1,234,567,890' |
| |
| # Expressing a percentage: |
| points = 19.0 |
| total = 22.0 |
| assert 'Correct answers: {:.2%}'.format(points/total) == 'Correct answers: 86.36%' |
| |
| # Using type-specific formatting: |
| import datetime |
| d = datetime.datetime(2010, 7, 4, 12, 15, 58) |
| assert '{:%Y-%m-%d %H:%M:%S}'.format(d) == '2010-07-04 12:15:58' |
| |
| # Nesting arguments and more complex examples: |
| tmp_strs = [] |
| for align, text in zip('<^>', ['left', 'center', 'right']): |
| tmp_strs.append('{0:{fill}{align}16}'.format(text, fill=align, align=align)) |
| assert tmp_strs == ['left<<<<<<<<<<<<', '^^^^^center^^^^^', '>>>>>>>>>>>right'] |
| |
| octets = [192, 168, 0, 1] |
| assert '{:02X}{:02X}{:02X}{:02X}'.format(*octets) == 'C0A80001' |
| |
| width = 5 |
| tmp_strs = [] |
| for num in range(5,12): |
| tmp_str = '' |
| for base in 'dXob': |
| tmp_str += ('{0:{width}{base}}'.format(num, base=base, width=width)) |
| tmp_strs.append(tmp_str) |
| assert tmp_strs == [' 5 5 5 101',\ |
| ' 6 6 6 110',\ |
| ' 7 7 7 111',\ |
| ' 8 8 10 1000',\ |
| ' 9 9 11 1001',\ |
| ' 10 A 12 1010',\ |
| ' 11 B 13 1011'] |
| |
| [case testChr] |
| # Some test cases are from https://docs.python.org/3/howto/unicode.html |
| |
| def try_invalid(x: int) -> bool: |
| try: |
| chr(x + int()) |
| return False |
| except ValueError: |
| return True |
| |
| def test_chr() -> None: |
| assert chr(57344) == '\ue000' |
| assert chr(0) == '\x00' |
| assert chr(65) == 'A' |
| assert chr(150) == '\x96' |
| try: |
| chr(-1) |
| assert False |
| except ValueError: |
| pass |
| try: |
| chr(1114112) |
| assert False |
| except ValueError: |
| pass |
| assert chr(1114111) == '\U0010ffff' |
| x = 0 |
| assert chr(x + int()) == '\x00' |
| x = 100 |
| assert chr(x + int()) == 'd' |
| x = 150 |
| assert chr(x + int()) == '\x96' |
| x = 257 |
| assert chr(x + int()) == 'ā' |
| x = 65537 |
| assert chr(x + int()) == '𐀁' |
| assert try_invalid(-1) |
| assert try_invalid(1114112) |
| |
| [case testOrd] |
| def test_ord() -> None: |
| assert ord('\ue000') == 57344 |
| s = "a\xac\u1234\u20ac\U00008000" |
| # ^^^^ two-digit hex escape |
| # ^^^^^^ four-digit Unicode escape |
| # ^^^^^^^^^^ eight-digit Unicode escape |
| l1 = [ord(c) for c in s] |
| assert l1 == [97, 172, 4660, 8364, 32768] |
| u = 'abcdé' |
| assert ord(u[-1]) == 233 |
| assert ord(b'a') == 97 |
| assert ord(b'a' + bytes()) == 97 |
| u2 = '\U0010ffff' |
| assert ord(u2) == 1114111 |
| try: |
| ord('aa') |
| assert False |
| except TypeError: |
| pass |
| |
| [case testDecode] |
| def test_decode() -> None: |
| assert "\N{GREEK CAPITAL LETTER DELTA}" == '\u0394' |
| assert "\u0394" == "\u0394" |
| assert "\U00000394" == '\u0394' |
| assert b'\x80abc'.decode('utf-8', 'replace') == '\ufffdabc' |
| assert b'\x80abc'.decode('utf-8', 'backslashreplace') == '\\x80abc' |
| assert b'abc'.decode() == 'abc' |
| assert b'abc'.decode('utf-8') == 'abc' |
| assert b'\x80abc'.decode('utf-8', 'ignore') == 'abc' |
| assert b'\x80abc'.decode('UTF-8', 'ignore') == 'abc' |
| assert b'\x80abc'.decode('Utf-8', 'ignore') == 'abc' |
| assert b'\x80abc'.decode('utf_8', 'ignore') == 'abc' |
| assert b'\x80abc'.decode('latin1', 'ignore') == '\x80abc' |
| assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('gbk', 'ignore') == '一二三' |
| assert b'\xd2\xbb\xb6\xfe\xc8\xfd'.decode('latin1', 'ignore') == 'Ò»¶þÈý' |
| assert b'Z\xc3\xbcrich'.decode("utf-8") == 'Zürich' |
| try: |
| b'Z\xc3\xbcrich'.decode('ascii') |
| assert False |
| except UnicodeDecodeError: |
| pass |
| assert bytearray(range(5)).decode() == '\x00\x01\x02\x03\x04' |
| b = bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd') |
| assert b.decode() == '你好' |
| assert b.decode('gbk') == '浣犲ソ' |
| assert b.decode('latin1') == 'ä½\xa0好' |
| |
| [case testEncode] |
| from testutil import assertRaises |
| |
| def test_encode() -> None: |
| u = chr(40960) + 'abcd' + chr(1972) |
| assert u.encode() == b'\xea\x80\x80abcd\xde\xb4' |
| assert u.encode('utf-8') == b'\xea\x80\x80abcd\xde\xb4' |
| with assertRaises(UnicodeEncodeError): |
| u.encode('ascii') |
| with assertRaises(LookupError): |
| u.encode('aaa') |
| assert u.encode('utf-8', 'aaaaaa') == b'\xea\x80\x80abcd\xde\xb4' |
| assert u.encode('ascii', 'ignore') == b'abcd' |
| assert u.encode('ASCII', 'ignore') == b'abcd' |
| assert u.encode('ascii', 'replace') == b'?abcd?' |
| assert u.encode('ascii', 'xmlcharrefreplace') == b'ꀀabcd޴' |
| assert u.encode('ascii', 'backslashreplace') == b'\\ua000abcd\\u07b4' |
| assert u.encode('ascii', 'namereplace') == b'\\N{YI SYLLABLE IT}abcd\\u07b4' |
| assert 'pythön!'.encode() == b'pyth\xc3\xb6n!' |
| assert '一二三'.encode('gbk') == b'\xd2\xbb\xb6\xfe\xc8\xfd' |
| assert u.encode('UTF-8', 'ignore') == b'\xea\x80\x80abcd\xde\xb4' |
| assert u.encode('Utf_8') == b'\xea\x80\x80abcd\xde\xb4' |
| assert u.encode('UTF_8') == b'\xea\x80\x80abcd\xde\xb4' |
| assert u'\u00E1'.encode('latin1') == b'\xe1' |
| with assertRaises(UnicodeEncodeError): |
| u.encode('latin1') |