17db96d56Sopenharmony_ciimport re 27db96d56Sopenharmony_cifrom unicodedata import ucd_3_2_0 as unicodedata 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_cidef gen_category(cats): 57db96d56Sopenharmony_ci for i in range(0, 0x110000): 67db96d56Sopenharmony_ci if unicodedata.category(chr(i)) in cats: 77db96d56Sopenharmony_ci yield(i) 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_cidef gen_bidirectional(cats): 107db96d56Sopenharmony_ci for i in range(0, 0x110000): 117db96d56Sopenharmony_ci if unicodedata.bidirectional(chr(i)) in cats: 127db96d56Sopenharmony_ci yield(i) 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_cidef compact_set(l): 157db96d56Sopenharmony_ci single = [] 167db96d56Sopenharmony_ci tuple = [] 177db96d56Sopenharmony_ci prev = None 187db96d56Sopenharmony_ci span = 0 197db96d56Sopenharmony_ci for e in l: 207db96d56Sopenharmony_ci if prev is None: 217db96d56Sopenharmony_ci prev = e 227db96d56Sopenharmony_ci span = 0 237db96d56Sopenharmony_ci continue 247db96d56Sopenharmony_ci if prev+span+1 != e: 257db96d56Sopenharmony_ci if span > 2: 267db96d56Sopenharmony_ci tuple.append((prev,prev+span+1)) 277db96d56Sopenharmony_ci else: 287db96d56Sopenharmony_ci for i in range(prev, prev+span+1): 297db96d56Sopenharmony_ci single.append(i) 307db96d56Sopenharmony_ci prev = e 317db96d56Sopenharmony_ci span = 0 327db96d56Sopenharmony_ci else: 337db96d56Sopenharmony_ci span += 1 347db96d56Sopenharmony_ci if span: 357db96d56Sopenharmony_ci tuple.append((prev,prev+span+1)) 367db96d56Sopenharmony_ci else: 377db96d56Sopenharmony_ci single.append(prev) 387db96d56Sopenharmony_ci if not single and len(tuple) == 1: 397db96d56Sopenharmony_ci tuple = "range(%d,%d)" % tuple[0] 407db96d56Sopenharmony_ci else: 417db96d56Sopenharmony_ci tuple = " + ".join("list(range(%d,%d))" % t for t in tuple) 427db96d56Sopenharmony_ci if not single: 437db96d56Sopenharmony_ci return "set(%s)" % tuple 447db96d56Sopenharmony_ci if not tuple: 457db96d56Sopenharmony_ci return "set(%r)" % (single,) 467db96d56Sopenharmony_ci return "set(%r + %s)" % (single, tuple) 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci############## Read the tables in the RFC ####################### 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ciwith open("rfc3454.txt") as f: 517db96d56Sopenharmony_ci data = f.readlines() 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_citables = [] 547db96d56Sopenharmony_cicurname = None 557db96d56Sopenharmony_cifor l in data: 567db96d56Sopenharmony_ci l = l.strip() 577db96d56Sopenharmony_ci if not l: 587db96d56Sopenharmony_ci continue 597db96d56Sopenharmony_ci # Skip RFC page breaks 607db96d56Sopenharmony_ci if l.startswith(("Hoffman & Blanchet", "RFC 3454")): 617db96d56Sopenharmony_ci continue 627db96d56Sopenharmony_ci # Find start/end lines 637db96d56Sopenharmony_ci m = re.match("----- (Start|End) Table ([A-Z](.[0-9])+) -----", l) 647db96d56Sopenharmony_ci if m: 657db96d56Sopenharmony_ci if m.group(1) == "Start": 667db96d56Sopenharmony_ci if curname: 677db96d56Sopenharmony_ci raise RuntimeError("Double Start", (curname, l)) 687db96d56Sopenharmony_ci curname = m.group(2) 697db96d56Sopenharmony_ci table = {} 707db96d56Sopenharmony_ci tables.append((curname, table)) 717db96d56Sopenharmony_ci continue 727db96d56Sopenharmony_ci else: 737db96d56Sopenharmony_ci if not curname: 747db96d56Sopenharmony_ci raise RuntimeError("End without start", l) 757db96d56Sopenharmony_ci if curname != m.group(2): 767db96d56Sopenharmony_ci raise RuntimeError("Unexpected end", l) 777db96d56Sopenharmony_ci curname = None 787db96d56Sopenharmony_ci continue 797db96d56Sopenharmony_ci if not curname: 807db96d56Sopenharmony_ci continue 817db96d56Sopenharmony_ci # Now we are in a table 827db96d56Sopenharmony_ci fields = l.split(";") 837db96d56Sopenharmony_ci if len(fields) > 1: 847db96d56Sopenharmony_ci # Drop comment field 857db96d56Sopenharmony_ci fields = fields[:-1] 867db96d56Sopenharmony_ci if len(fields) == 1: 877db96d56Sopenharmony_ci fields = fields[0].split("-") 887db96d56Sopenharmony_ci if len(fields) > 1: 897db96d56Sopenharmony_ci # range 907db96d56Sopenharmony_ci try: 917db96d56Sopenharmony_ci start, end = fields 927db96d56Sopenharmony_ci except ValueError: 937db96d56Sopenharmony_ci raise RuntimeError("Unpacking problem", l) 947db96d56Sopenharmony_ci else: 957db96d56Sopenharmony_ci start = end = fields[0] 967db96d56Sopenharmony_ci start = int(start, 16) 977db96d56Sopenharmony_ci end = int(end, 16) 987db96d56Sopenharmony_ci for i in range(start, end+1): 997db96d56Sopenharmony_ci table[i] = i 1007db96d56Sopenharmony_ci else: 1017db96d56Sopenharmony_ci code, value = fields 1027db96d56Sopenharmony_ci value = value.strip() 1037db96d56Sopenharmony_ci if value: 1047db96d56Sopenharmony_ci value = [int(v, 16) for v in value.split(" ")] 1057db96d56Sopenharmony_ci else: 1067db96d56Sopenharmony_ci # table B.1 1077db96d56Sopenharmony_ci value = None 1087db96d56Sopenharmony_ci table[int(code, 16)] = value 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci########### Generate compact Python versions of the tables ############# 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ciprint("""# This file is generated by mkstringprep.py. DO NOT EDIT. 1137db96d56Sopenharmony_ci\"\"\"Library that exposes various tables found in the StringPrep RFC 3454. 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ciThere are two kinds of tables: sets, for which a member test is provided, 1167db96d56Sopenharmony_ciand mappings, for which a mapping function is provided. 1177db96d56Sopenharmony_ci\"\"\" 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_cifrom unicodedata import ucd_3_2_0 as unicodedata 1207db96d56Sopenharmony_ci""") 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ciprint("assert unicodedata.unidata_version == %r" % (unicodedata.unidata_version,)) 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci# A.1 is the table of unassigned characters 1257db96d56Sopenharmony_ci# XXX Plane 15 PUA is listed as unassigned in Python. 1267db96d56Sopenharmony_ciname, table = tables[0] 1277db96d56Sopenharmony_cidel tables[0] 1287db96d56Sopenharmony_ciassert name == "A.1" 1297db96d56Sopenharmony_citable = set(table.keys()) 1307db96d56Sopenharmony_ciCn = set(gen_category(["Cn"])) 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci# FDD0..FDEF are process internal codes 1337db96d56Sopenharmony_ciCn -= set(range(0xFDD0, 0xFDF0)) 1347db96d56Sopenharmony_ci# not a character 1357db96d56Sopenharmony_ciCn -= set(range(0xFFFE, 0x110000, 0x10000)) 1367db96d56Sopenharmony_ciCn -= set(range(0xFFFF, 0x110000, 0x10000)) 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci# assert table == Cn 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ciprint(""" 1417db96d56Sopenharmony_cidef in_table_a1(code): 1427db96d56Sopenharmony_ci if unicodedata.category(code) != 'Cn': return False 1437db96d56Sopenharmony_ci c = ord(code) 1447db96d56Sopenharmony_ci if 0xFDD0 <= c < 0xFDF0: return False 1457db96d56Sopenharmony_ci return (c & 0xFFFF) not in (0xFFFE, 0xFFFF) 1467db96d56Sopenharmony_ci""") 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci# B.1 cannot easily be derived 1497db96d56Sopenharmony_ciname, table = tables[0] 1507db96d56Sopenharmony_cidel tables[0] 1517db96d56Sopenharmony_ciassert name == "B.1" 1527db96d56Sopenharmony_citable = sorted(table.keys()) 1537db96d56Sopenharmony_ciprint(""" 1547db96d56Sopenharmony_cib1_set = """ + compact_set(table) + """ 1557db96d56Sopenharmony_cidef in_table_b1(code): 1567db96d56Sopenharmony_ci return ord(code) in b1_set 1577db96d56Sopenharmony_ci""") 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci# B.2 and B.3 is case folding. 1607db96d56Sopenharmony_ci# It takes CaseFolding.txt into account, which is 1617db96d56Sopenharmony_ci# not available in the Python database. Since 1627db96d56Sopenharmony_ci# B.2 is derived from B.3, we process B.3 first. 1637db96d56Sopenharmony_ci# B.3 supposedly *is* CaseFolding-3.2.0.txt. 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ciname, table_b2 = tables[0] 1667db96d56Sopenharmony_cidel tables[0] 1677db96d56Sopenharmony_ciassert name == "B.2" 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_ciname, table_b3 = tables[0] 1707db96d56Sopenharmony_cidel tables[0] 1717db96d56Sopenharmony_ciassert name == "B.3" 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci# B.3 is mostly Python's .lower, except for a number 1747db96d56Sopenharmony_ci# of special cases, e.g. considering canonical forms. 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_cib3_exceptions = {} 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_cifor k,v in table_b2.items(): 1797db96d56Sopenharmony_ci if list(map(ord, chr(k).lower())) != v: 1807db96d56Sopenharmony_ci b3_exceptions[k] = "".join(map(chr,v)) 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_cib3 = sorted(b3_exceptions.items()) 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ciprint(""" 1857db96d56Sopenharmony_cib3_exceptions = {""") 1867db96d56Sopenharmony_cifor i, kv in enumerate(b3): 1877db96d56Sopenharmony_ci print("0x%x:%a," % kv, end=' ') 1887db96d56Sopenharmony_ci if i % 4 == 3: 1897db96d56Sopenharmony_ci print() 1907db96d56Sopenharmony_ciprint("}") 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ciprint(""" 1937db96d56Sopenharmony_cidef map_table_b3(code): 1947db96d56Sopenharmony_ci r = b3_exceptions.get(ord(code)) 1957db96d56Sopenharmony_ci if r is not None: return r 1967db96d56Sopenharmony_ci return code.lower() 1977db96d56Sopenharmony_ci""") 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_cidef map_table_b3(code): 2007db96d56Sopenharmony_ci r = b3_exceptions.get(ord(code)) 2017db96d56Sopenharmony_ci if r is not None: return r 2027db96d56Sopenharmony_ci return code.lower() 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ci# B.2 is case folding for NFKC. This is the same as B.3, 2057db96d56Sopenharmony_ci# except where NormalizeWithKC(Fold(a)) != 2067db96d56Sopenharmony_ci# NormalizeWithKC(Fold(NormalizeWithKC(Fold(a)))) 2077db96d56Sopenharmony_ci 2087db96d56Sopenharmony_cidef map_table_b2(a): 2097db96d56Sopenharmony_ci al = map_table_b3(a) 2107db96d56Sopenharmony_ci b = unicodedata.normalize("NFKC", al) 2117db96d56Sopenharmony_ci bl = "".join([map_table_b3(ch) for ch in b]) 2127db96d56Sopenharmony_ci c = unicodedata.normalize("NFKC", bl) 2137db96d56Sopenharmony_ci if b != c: 2147db96d56Sopenharmony_ci return c 2157db96d56Sopenharmony_ci else: 2167db96d56Sopenharmony_ci return al 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_cispecials = {} 2197db96d56Sopenharmony_cifor k,v in table_b2.items(): 2207db96d56Sopenharmony_ci if list(map(ord, map_table_b2(chr(k)))) != v: 2217db96d56Sopenharmony_ci specials[k] = v 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ci# B.3 should not add any additional special cases 2247db96d56Sopenharmony_ciassert specials == {} 2257db96d56Sopenharmony_ci 2267db96d56Sopenharmony_ciprint(""" 2277db96d56Sopenharmony_cidef map_table_b2(a): 2287db96d56Sopenharmony_ci al = map_table_b3(a) 2297db96d56Sopenharmony_ci b = unicodedata.normalize("NFKC", al) 2307db96d56Sopenharmony_ci bl = "".join([map_table_b3(ch) for ch in b]) 2317db96d56Sopenharmony_ci c = unicodedata.normalize("NFKC", bl) 2327db96d56Sopenharmony_ci if b != c: 2337db96d56Sopenharmony_ci return c 2347db96d56Sopenharmony_ci else: 2357db96d56Sopenharmony_ci return al 2367db96d56Sopenharmony_ci""") 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci# C.1.1 is a table with a single character 2397db96d56Sopenharmony_ciname, table = tables[0] 2407db96d56Sopenharmony_cidel tables[0] 2417db96d56Sopenharmony_ciassert name == "C.1.1" 2427db96d56Sopenharmony_ciassert table == {0x20:0x20} 2437db96d56Sopenharmony_ci 2447db96d56Sopenharmony_ciprint(""" 2457db96d56Sopenharmony_cidef in_table_c11(code): 2467db96d56Sopenharmony_ci return code == " " 2477db96d56Sopenharmony_ci""") 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci# C.1.2 is the rest of all space characters 2507db96d56Sopenharmony_ciname, table = tables[0] 2517db96d56Sopenharmony_cidel tables[0] 2527db96d56Sopenharmony_ciassert name == "C.1.2" 2537db96d56Sopenharmony_ci 2547db96d56Sopenharmony_ci# table = set(table.keys()) 2557db96d56Sopenharmony_ci# Zs = set(gen_category(["Zs"])) - {0x20} 2567db96d56Sopenharmony_ci# assert Zs == table 2577db96d56Sopenharmony_ci 2587db96d56Sopenharmony_ciprint(""" 2597db96d56Sopenharmony_cidef in_table_c12(code): 2607db96d56Sopenharmony_ci return unicodedata.category(code) == "Zs" and code != " " 2617db96d56Sopenharmony_ci 2627db96d56Sopenharmony_cidef in_table_c11_c12(code): 2637db96d56Sopenharmony_ci return unicodedata.category(code) == "Zs" 2647db96d56Sopenharmony_ci""") 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ci# C.2.1 ASCII control characters 2677db96d56Sopenharmony_ciname, table_c21 = tables[0] 2687db96d56Sopenharmony_cidel tables[0] 2697db96d56Sopenharmony_ciassert name == "C.2.1" 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ciCc = set(gen_category(["Cc"])) 2727db96d56Sopenharmony_ciCc_ascii = Cc & set(range(128)) 2737db96d56Sopenharmony_citable_c21 = set(table_c21.keys()) 2747db96d56Sopenharmony_ciassert Cc_ascii == table_c21 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ciprint(""" 2777db96d56Sopenharmony_cidef in_table_c21(code): 2787db96d56Sopenharmony_ci return ord(code) < 128 and unicodedata.category(code) == "Cc" 2797db96d56Sopenharmony_ci""") 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_ci# C.2.2 Non-ASCII control characters. It also includes 2827db96d56Sopenharmony_ci# a number of characters in category Cf. 2837db96d56Sopenharmony_ciname, table_c22 = tables[0] 2847db96d56Sopenharmony_cidel tables[0] 2857db96d56Sopenharmony_ciassert name == "C.2.2" 2867db96d56Sopenharmony_ci 2877db96d56Sopenharmony_ciCc_nonascii = Cc - Cc_ascii 2887db96d56Sopenharmony_citable_c22 = set(table_c22.keys()) 2897db96d56Sopenharmony_ciassert len(Cc_nonascii - table_c22) == 0 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_cispecials = list(table_c22 - Cc_nonascii) 2927db96d56Sopenharmony_cispecials.sort() 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ciprint("""c22_specials = """ + compact_set(specials) + """ 2957db96d56Sopenharmony_cidef in_table_c22(code): 2967db96d56Sopenharmony_ci c = ord(code) 2977db96d56Sopenharmony_ci if c < 128: return False 2987db96d56Sopenharmony_ci if unicodedata.category(code) == "Cc": return True 2997db96d56Sopenharmony_ci return c in c22_specials 3007db96d56Sopenharmony_ci 3017db96d56Sopenharmony_cidef in_table_c21_c22(code): 3027db96d56Sopenharmony_ci return unicodedata.category(code) == "Cc" or \\ 3037db96d56Sopenharmony_ci ord(code) in c22_specials 3047db96d56Sopenharmony_ci""") 3057db96d56Sopenharmony_ci 3067db96d56Sopenharmony_ci# C.3 Private use 3077db96d56Sopenharmony_ciname, table = tables[0] 3087db96d56Sopenharmony_cidel tables[0] 3097db96d56Sopenharmony_ciassert name == "C.3" 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ciCo = set(gen_category(["Co"])) 3127db96d56Sopenharmony_ciassert set(table.keys()) == Co 3137db96d56Sopenharmony_ci 3147db96d56Sopenharmony_ciprint(""" 3157db96d56Sopenharmony_cidef in_table_c3(code): 3167db96d56Sopenharmony_ci return unicodedata.category(code) == "Co" 3177db96d56Sopenharmony_ci""") 3187db96d56Sopenharmony_ci 3197db96d56Sopenharmony_ci# C.4 Non-character code points, xFFFE, xFFFF 3207db96d56Sopenharmony_ci# plus process internal codes 3217db96d56Sopenharmony_ciname, table = tables[0] 3227db96d56Sopenharmony_cidel tables[0] 3237db96d56Sopenharmony_ciassert name == "C.4" 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_cinonchar = set(range(0xFDD0,0xFDF0)) 3267db96d56Sopenharmony_cinonchar.update(range(0xFFFE,0x110000,0x10000)) 3277db96d56Sopenharmony_cinonchar.update(range(0xFFFF,0x110000,0x10000)) 3287db96d56Sopenharmony_citable = set(table.keys()) 3297db96d56Sopenharmony_ciassert table == nonchar 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ciprint(""" 3327db96d56Sopenharmony_cidef in_table_c4(code): 3337db96d56Sopenharmony_ci c = ord(code) 3347db96d56Sopenharmony_ci if c < 0xFDD0: return False 3357db96d56Sopenharmony_ci if c < 0xFDF0: return True 3367db96d56Sopenharmony_ci return (ord(code) & 0xFFFF) in (0xFFFE, 0xFFFF) 3377db96d56Sopenharmony_ci""") 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ci# C.5 Surrogate codes 3407db96d56Sopenharmony_ciname, table = tables[0] 3417db96d56Sopenharmony_cidel tables[0] 3427db96d56Sopenharmony_ciassert name == "C.5" 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ciCs = set(gen_category(["Cs"])) 3457db96d56Sopenharmony_ciassert set(table.keys()) == Cs 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ciprint(""" 3487db96d56Sopenharmony_cidef in_table_c5(code): 3497db96d56Sopenharmony_ci return unicodedata.category(code) == "Cs" 3507db96d56Sopenharmony_ci""") 3517db96d56Sopenharmony_ci 3527db96d56Sopenharmony_ci# C.6 Inappropriate for plain text 3537db96d56Sopenharmony_ciname, table = tables[0] 3547db96d56Sopenharmony_cidel tables[0] 3557db96d56Sopenharmony_ciassert name == "C.6" 3567db96d56Sopenharmony_ci 3577db96d56Sopenharmony_citable = sorted(table.keys()) 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ciprint(""" 3607db96d56Sopenharmony_cic6_set = """ + compact_set(table) + """ 3617db96d56Sopenharmony_cidef in_table_c6(code): 3627db96d56Sopenharmony_ci return ord(code) in c6_set 3637db96d56Sopenharmony_ci""") 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci# C.7 Inappropriate for canonical representation 3667db96d56Sopenharmony_ciname, table = tables[0] 3677db96d56Sopenharmony_cidel tables[0] 3687db96d56Sopenharmony_ciassert name == "C.7" 3697db96d56Sopenharmony_ci 3707db96d56Sopenharmony_citable = sorted(table.keys()) 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ciprint(""" 3737db96d56Sopenharmony_cic7_set = """ + compact_set(table) + """ 3747db96d56Sopenharmony_cidef in_table_c7(code): 3757db96d56Sopenharmony_ci return ord(code) in c7_set 3767db96d56Sopenharmony_ci""") 3777db96d56Sopenharmony_ci 3787db96d56Sopenharmony_ci# C.8 Change display properties or are deprecated 3797db96d56Sopenharmony_ciname, table = tables[0] 3807db96d56Sopenharmony_cidel tables[0] 3817db96d56Sopenharmony_ciassert name == "C.8" 3827db96d56Sopenharmony_ci 3837db96d56Sopenharmony_citable = sorted(table.keys()) 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_ciprint(""" 3867db96d56Sopenharmony_cic8_set = """ + compact_set(table) + """ 3877db96d56Sopenharmony_cidef in_table_c8(code): 3887db96d56Sopenharmony_ci return ord(code) in c8_set 3897db96d56Sopenharmony_ci""") 3907db96d56Sopenharmony_ci 3917db96d56Sopenharmony_ci# C.9 Tagging characters 3927db96d56Sopenharmony_ciname, table = tables[0] 3937db96d56Sopenharmony_cidel tables[0] 3947db96d56Sopenharmony_ciassert name == "C.9" 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_citable = sorted(table.keys()) 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ciprint(""" 3997db96d56Sopenharmony_cic9_set = """ + compact_set(table) + """ 4007db96d56Sopenharmony_cidef in_table_c9(code): 4017db96d56Sopenharmony_ci return ord(code) in c9_set 4027db96d56Sopenharmony_ci""") 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci# D.1 Characters with bidirectional property "R" or "AL" 4057db96d56Sopenharmony_ciname, table = tables[0] 4067db96d56Sopenharmony_cidel tables[0] 4077db96d56Sopenharmony_ciassert name == "D.1" 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ciRandAL = set(gen_bidirectional(["R","AL"])) 4107db96d56Sopenharmony_ciassert set(table.keys()) == RandAL 4117db96d56Sopenharmony_ci 4127db96d56Sopenharmony_ciprint(""" 4137db96d56Sopenharmony_cidef in_table_d1(code): 4147db96d56Sopenharmony_ci return unicodedata.bidirectional(code) in ("R","AL") 4157db96d56Sopenharmony_ci""") 4167db96d56Sopenharmony_ci 4177db96d56Sopenharmony_ci# D.2 Characters with bidirectional property "L" 4187db96d56Sopenharmony_ciname, table = tables[0] 4197db96d56Sopenharmony_cidel tables[0] 4207db96d56Sopenharmony_ciassert name == "D.2" 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ciL = set(gen_bidirectional(["L"])) 4237db96d56Sopenharmony_ciassert set(table.keys()) == L 4247db96d56Sopenharmony_ci 4257db96d56Sopenharmony_ciprint(""" 4267db96d56Sopenharmony_cidef in_table_d2(code): 4277db96d56Sopenharmony_ci return unicodedata.bidirectional(code) == "L" 4287db96d56Sopenharmony_ci""") 429