test_normalization.py 3.41 KB
Newer Older
1
from test.support import run_unittest, open_urlresource
2 3
import unittest

4
from http.client import HTTPException
5
import sys
6
import os
7
from unicodedata import normalize, unidata_version
8

Skip Montanaro's avatar
Skip Montanaro committed
9
TESTDATAFILE = "NormalizationTest.txt"
10 11
TESTDATAURL = "http://www.unicode.org/Public/" + unidata_version + "/ucd/" + TESTDATAFILE

12 13 14 15
# Verify we have the correct version of the test data file.
TESTDATAPATH = os.path.join(os.path.dirname(__file__), "data", TESTDATAFILE)
if os.path.exists(TESTDATAPATH):
    f = open(TESTDATAPATH, encoding='utf-8')
16 17 18
    l = f.readline()
    f.close()
    if not unidata_version in l:
19
        os.unlink(testdatafile)
20

21
class RangeError(Exception):
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    pass

def NFC(str):
    return normalize("NFC", str)

def NFKC(str):
    return normalize("NFKC", str)

def NFD(str):
    return normalize("NFD", str)

def NFKD(str):
    return normalize("NFKD", str)

def unistr(data):
    data = [int(x, 16) for x in data.split(" ")]
    for x in data:
        if x > sys.maxunicode:
            raise RangeError
41
    return "".join([chr(x) for x in data])
42

43 44 45
class NormalizationTest(unittest.TestCase):
    def test_main(self):
        part1_data = {}
46 47 48
        # Hit the exception early
        try:
            open_urlresource(TESTDATAURL, encoding="utf-8")
49
        except (IOError, HTTPException):
50
            self.skipTest("Could not retrieve " + TESTDATAURL)
51
        for line in open_urlresource(TESTDATAURL, encoding="utf-8"):
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
            if '#' in line:
                line = line.split('#')[0]
            line = line.strip()
            if not line:
                continue
            if line.startswith("@Part"):
                part = line.split()[0]
                continue
            if part == "@Part3":
                # XXX we don't support PRI #29 yet, so skip these tests for now
                continue
            try:
                c1,c2,c3,c4,c5 = [unistr(x) for x in line.split(';')[:-1]]
            except RangeError:
                # Skip unsupported characters;
                # try atleast adding c1 if we are in part1
                if part == "@Part1":
                    try:
                        c1 = unistr(line.split(';')[0])
                    except RangeError:
                        pass
                    else:
                        part1_data[c1] = 1
                continue

            # Perform tests
78 79 80 81 82
            self.assertTrue(c2 ==  NFC(c1) ==  NFC(c2) ==  NFC(c3), line)
            self.assertTrue(c4 ==  NFC(c4) ==  NFC(c5), line)
            self.assertTrue(c3 ==  NFD(c1) ==  NFD(c2) ==  NFD(c3), line)
            self.assertTrue(c5 ==  NFD(c4) ==  NFD(c5), line)
            self.assertTrue(c4 == NFKC(c1) == NFKC(c2) == \
83 84
                            NFKC(c3) == NFKC(c4) == NFKC(c5),
                            line)
85
            self.assertTrue(c5 == NFKD(c1) == NFKD(c2) == \
86 87 88 89
                            NFKD(c3) == NFKD(c4) == NFKD(c5),
                            line)

            # Record part 1 data
90
            if part == "@Part1":
91 92 93 94
                part1_data[c1] = 1

        # Perform tests for all other data
        for c in range(sys.maxunicode+1):
95
            X = chr(c)
96 97
            if X in part1_data:
                continue
98
            self.assertTrue(X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X), c)
99 100 101

    def test_bug_834676(self):
        # Check for bug 834676
102
        normalize('NFC', '\ud55c\uae00')
103 104 105 106


def test_main():
    run_unittest(NormalizationTest)
107

108 109
if __name__ == "__main__":
    test_main()