from unittest import TestCase from _pyrepl.utils import str_width, wlen, prev_next_window, gen_colors class TestUtils(TestCase): def test_str_width(self): characters = [ 'a', '1', '_', '!', '\x1a', '\u263A', '\uffb9', '\N{LATIN SMALL LETTER E WITH ACUTE}', # é '\N{LATIN SMALL LETTER E WITH CEDILLA}', # ȩ '\u00ad', ] for c in characters: self.assertEqual(str_width(c), 1) zero_width_characters = [ '\N{COMBINING ACUTE ACCENT}', '\N{ZERO WIDTH JOINER}', '\u2028', '\u2029', ] for c in zero_width_characters: with self.subTest(character=c): self.assertEqual(str_width(c), 0) characters = [chr(99989), chr(99999)] for c in characters: self.assertEqual(str_width(c), 2) def test_wlen(self): for c in ['a', 'b', '1', '!', '_']: self.assertEqual(wlen(c), 1) self.assertEqual(wlen('\x1a'), 2) char_east_asian_width_N = chr(3800) self.assertEqual(wlen(char_east_asian_width_N), 1) char_east_asian_width_W = chr(4352) self.assertEqual(wlen(char_east_asian_width_W), 2) self.assertEqual(wlen('hello'), 5) self.assertEqual(wlen('hello' + '\x1a'), 7) self.assertEqual(wlen('e\N{COMBINING ACUTE ACCENT}'), 1) self.assertEqual(wlen('a\N{ZERO WIDTH JOINER}b'), 2) def test_prev_next_window(self): def gen_normal(): yield 1 yield 2 yield 3 yield 4 pnw = prev_next_window(gen_normal()) self.assertEqual(next(pnw), (None, 1, 2)) self.assertEqual(next(pnw), (1, 2, 3)) self.assertEqual(next(pnw), (2, 3, 4)) self.assertEqual(next(pnw), (3, 4, None)) with self.assertRaises(StopIteration): next(pnw) def gen_short(): yield 1 pnw = prev_next_window(gen_short()) self.assertEqual(next(pnw), (None, 1, None)) with self.assertRaises(StopIteration): next(pnw) def gen_raise(): yield from gen_normal() 1/0 pnw = prev_next_window(gen_raise()) self.assertEqual(next(pnw), (None, 1, 2)) self.assertEqual(next(pnw), (1, 2, 3)) self.assertEqual(next(pnw), (2, 3, 4)) self.assertEqual(next(pnw), (3, 4, None)) with self.assertRaises(ZeroDivisionError): next(pnw) def test_gen_colors_keyword_highlighting(self): cases = [ # no highlights ("a.set", [(".", "op")]), ("obj.list", [(".", "op")]), ("obj.match", [(".", "op")]), ("b. \\\n format", [(".", "op")]), # highlights ("set", [("set", "builtin")]), ("list", [("list", "builtin")]), (" \n dict", [("dict", "builtin")]), ] for code, expected_highlights in cases: with self.subTest(code=code): colors = list(gen_colors(code)) # Extract (text, tag) pairs for comparison actual_highlights = [] for color in colors: span_text = code[color.span.start:color.span.end + 1] actual_highlights.append((span_text, color.tag)) self.assertEqual(actual_highlights, expected_highlights)