Пример #1
0
def _confuse_internal(us, cclasses=['all'], asciify=True, smart=False):
    '''
    Fold input for homograph comparison. Does not handle the special cases that require postprocessing or multicharacter matching.
    '''
    assert type(us) == type(u'')
    global confusemap, confusables
    if cclasses == ['all'] and asciify and confusemap and not smart:
        return u''.join([
            confusemap.get(dest, unicodedata.normalize('NFC', dest.lower()))
            for dest in unichars(unicodedata.normalize('NFKD', us))
        ])
    if not confusemap:
        _slow_init()
    out = []
    for ch in unichars(unicodedata.normalize('NFKD', us)):
        b = ch
        b2 = u''
        for cclass in cclasses:
            if ch in confusables[cclass]:
                if smart:
                    b = random.choice([b] + list(confusables[cclass][ch]))
                    break
                else:
                    for rep in confusables[cclass][ch]:
                        if unilen(rep) > unilen(b2) or rep < b2:
                            b, b2 = [rep] * 2
        out.append(b)
    out = u''.join(out)
    if asciify:
        out = unicodedata.normalize('NFC', out.lower())
    if out != us and cclasses == ['all'] and not smart:
        out = _confuse_internal(out, cclasses, asciify)
    return out
Пример #2
0
def saslprep(s, allow_unassigned = False):
    '''
    Prepare Unicode string s according to SASLprep: Stringprep Profile for
    User Names and Passwords, a.k.a. RFC 4013

    If the optional parameter allow_unassigned is set to True,
    unassigned codepoints will be allowed. This is recommended for
    query terms and other non-storing situations only.

    The return value is a Unicode string appropriately prepared.

    Disallowed input leads to a ValueError.
    '''
    if type(s) != type(u''):
        raise TypeError("input must be a Unicode string")
    # phase 1: mapping
    s = u''.join([ stringprep.in_table_c12(ch) and u' ' or ch for ch in unichars(s) if not stringprep.in_table_b1(ch) ])
    # phase 2: normalization
    s = unicodedata.normalize('NFKC', s)
    # phase 3: prohibition
    for ch in unichars(s):
        if stringprep.in_table_c12(ch):
            raise ValueError("prohibited non-ASCII space character")
        if stringprep.in_table_c21(ch):
            raise ValueError("prohibited ASCII control character")
        if stringprep.in_table_c22(ch):
            raise ValueError("prohibited non-ASCII control character")
        if stringprep.in_table_c3(ch):
            raise ValueError("prohibited private use character")
        if stringprep.in_table_c4(ch):
            raise ValueError("prohibited non-character code point")
        if stringprep.in_table_c5(ch):
            raise ValueError("prohibited surrogate code point")
        if stringprep.in_table_c6(ch):
            raise ValueError("prohibited character inappropriate for plain text")
        if stringprep.in_table_c7(ch):
            raise ValueError("prohibited character inappropriate for canonical representation")
        if stringprep.in_table_c8(ch):
            raise ValueError("prohibited character changing display properties, or a deprecated character")
        if stringprep.in_table_c9(ch):
            raise ValueError("prohibited tagging character")
    # phase 4: bidi check
    bidi_map = ''.join([ stringprep.in_table_d1(ch) and 'r' or stringprep.in_table_d2(ch) and 'l' or 'x' for ch in unichars(s) ])
    if 'r' in bidi_map:
        if 'l' in bidi_map:
            raise ValueError("prohibited mixture of strong left-to-right and right-to-left text")
        if bidi_map[0] != 'r' or bidi_map[-1] != 'r':
            raise ValueError("string containing right-to-left text must start and end with right-to-left text")
    # phase 5: unassigned check
    if not allow_unassigned:
        for ch in unichars(s):
            if stringprep.in_table_a1(ch):
                raise ValueError("prohibited unassigned code point")
    return s
Пример #3
0
def _confuse_internal(us, cclasses = [ 'all' ], asciify = True, smart = False):
    '''
    Fold input for homograph comparison. Does not handle the special cases that require postprocessing or multicharacter matching.
    '''
    assert type(us) == type(u'')
    global confusemap, confusables
    if cclasses == [ 'all' ] and asciify and confusemap and not smart:
        return u''.join([ confusemap.get(dest, unicodedata.normalize('NFC', dest.lower())) for dest in unichars(unicodedata.normalize('NFKD', us)) ])
    if not confusemap:
        _slow_init()
    out = []
    for ch in unichars(unicodedata.normalize('NFKD', us)):
        b = ch
        b2 = u''
        for cclass in cclasses:
            if ch in confusables[cclass]:
                if smart:
                    b = random.choice([ b ] + list(confusables[cclass][ch]))
                    break
                else:
                    for rep in confusables[cclass][ch]:
                        if unilen(rep) > unilen(b2) or rep < b2:
                            b, b2 = [rep] * 2
        out.append(b)
    out = u''.join(out)
    if asciify:
        out = unicodedata.normalize('NFC', out.lower())
    if out != us and cclasses == [ 'all' ] and not smart:
        out = _confuse_internal(out, cclasses, asciify)
    return out
Пример #4
0
def saslprep(s, allow_unassigned=False):
    '''
    Prepare Unicode string s according to SASLprep: Stringprep Profile for
    User Names and Passwords, a.k.a. RFC 4013

    If the optional parameter allow_unassigned is set to True,
    unassigned codepoints will be allowed. This is recommended for
    query terms and other non-storing situations only.

    The return value is a Unicode string appropriately prepared.

    Disallowed input leads to a ValueError.
    '''
    if type(s) != type(u''):
        raise TypeError("input must be a Unicode string")
    # phase 1: mapping
    s = u''.join([
        stringprep.in_table_c12(ch) and u' ' or ch for ch in unichars(s)
        if not stringprep.in_table_b1(ch)
    ])
    # phase 2: normalization
    s = unicodedata.normalize('NFKC', s)
    # phase 3: prohibition
    for ch in unichars(s):
        if stringprep.in_table_c12(ch):
            raise ValueError("prohibited non-ASCII space character")
        if stringprep.in_table_c21(ch):
            raise ValueError("prohibited ASCII control character")
        if stringprep.in_table_c22(ch):
            raise ValueError("prohibited non-ASCII control character")
        if stringprep.in_table_c3(ch):
            raise ValueError("prohibited private use character")
        if stringprep.in_table_c4(ch):
            raise ValueError("prohibited non-character code point")
        if stringprep.in_table_c5(ch):
            raise ValueError("prohibited surrogate code point")
        if stringprep.in_table_c6(ch):
            raise ValueError(
                "prohibited character inappropriate for plain text")
        if stringprep.in_table_c7(ch):
            raise ValueError(
                "prohibited character inappropriate for canonical representation"
            )
        if stringprep.in_table_c8(ch):
            raise ValueError(
                "prohibited character changing display properties, or a deprecated character"
            )
        if stringprep.in_table_c9(ch):
            raise ValueError("prohibited tagging character")
    # phase 4: bidi check
    bidi_map = ''.join([
        stringprep.in_table_d1(ch) and 'r'
        or stringprep.in_table_d2(ch) and 'l' or 'x' for ch in unichars(s)
    ])
    if 'r' in bidi_map:
        if 'l' in bidi_map:
            raise ValueError(
                "prohibited mixture of strong left-to-right and right-to-left text"
            )
        if bidi_map[0] != 'r' or bidi_map[-1] != 'r':
            raise ValueError(
                "string containing right-to-left text must start and end with right-to-left text"
            )
    # phase 5: unassigned check
    if not allow_unassigned:
        for ch in unichars(s):
            if stringprep.in_table_a1(ch):
                raise ValueError("prohibited unassigned code point")
    return s
Пример #5
0
def test():
    '''
    Small smoke test to make sure this module is not broken.
    '''
    assert unilen(u'\U0010fffd') == 1
    assert len(u'Hello, world!') == unilen(u'Hello, world!')
    assert uniord(u'\U0010fffd') == 0x10fffd
    assert uniord(u'H') == ord(u'H')
    assert unichr(0x10fffd) == u'\U0010fffd'
    assert unichr(ord(u'H')) == u'H'
    assert [ ch for ch in unichars(u'H\U0010fffd') ] == [ 'H', u'\U0010fffd' ]
    assert confuse(u'Hello, world!', [ 'all' ], True) == confuse(u'he110, w0r1d!', [ 'all' ], True)
    assert confuse(u'Sergey Brin') == confuse(u'5e\N{GREEK SMALL LETTER GAMMA}g\N{GREEK SMALL LETTER EPSILON}\N{GREEK SMALL LETTER UPSILON} \N{GREEK CAPITAL LETTER BETA}r1\N{GREEK CAPITAL LETTER NU}')
    assert confuse(u'He\N{LATIN SMALL LETTER SHARP S}e') == confuse(u'Hesse')
    assert confuse(u'\N{GREEK CAPITAL LETTER KAPPA}\N{GREEK SMALL LETTER NU}\N{GREEK SMALL LETTER OMEGA}\N{GREEK SMALL LETTER SIGMA}\N{GREEK SMALL LETTER OMICRON WITH TONOS}\N{GREEK SMALL LETTER FINAL SIGMA}') == confuse(u'Kv\N{OHM SIGN}co\N{COMBINING ACUTE ACCENT}c')
    assert confuse(u'\N{LATIN SMALL LETTER I}') == confuse(u'\N{LATIN CAPITAL LETTER I}')
    assert confuse(u'\N{LATIN SMALL LETTER I}\N{COMBINING DOT ABOVE}') == confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}') == confuse(u'\N{LATIN CAPITAL LETTER I}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}') == confuse(u'\N{LATIN SMALL LETTER I}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}') == confuse(u'\N{LATIN SMALL LETTER I}\N{COMBINING DOT ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}') == confuse(u'\N{LATIN CAPITAL LETTER I}\N{COMBINING DOT ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}') == confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER I}\N{COMBINING DOT ABOVE}') == confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}') == confuse(u'\N{DIGIT ONE}\N{COMBINING DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER O WITH HORN}') == confuse(u'\N{DIGIT ZERO}\N{COMBINING HORN}')
    assert confuse(u'\N{LATIN SMALL LETTER O WITH HORN}') == confuse(u'\N{DIGIT ZERO}\N{COMBINING HORN}')
    assert confuse(u'\N{LATIN SMALL LETTER I}') == confuse(u'\N{LATIN SMALL LETTER I}\N{COMBINING DOT ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER I}') == confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}') == confuse(u'\N{DIGIT ONE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER O WITH HORN}') == confuse(u'\N{LATIN CAPITAL LETTER O}\N{SPACE}\N{COMBINING COMMA ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER O WITH HORN}') == confuse(u'\N{LATIN CAPITAL LETTER O}\N{SPACE}\N{COMBINING COMMA ABOVE}')

    # NOTE: this is a weak bidi homograph for "i love you"
    assert confuse(u'ڸ٥ﻻ ﻉ√٥ﺎ ٱ') == confuse(u'\u06b8\u0665\ufefb \ufec9\u221a\u0665\ufe8e \u0671')
    assert confuse(u'\u06b8\u0665\u0644\u0627 \u0639\u221a\u0665\u0627 \u0671') == confuse(u'ڸ٥ﻻ ﻉ√٥ﺎ ٱ')
    assert (confuse(u''.join(u'''
    0\u09e6\u2080\u0d02\u0585\u3007\U0001d70a\U0001d5ae\u1d0f\U0001d40e\u1810\U0001d512\U0001d7f6\U0001d594\U0001d616\U0001d698\u0966\u101d\U0001d6f0\u039f\u041e\u0d20\U0001d7ec\uff4f\u0c66\U0001d630\U0001d428\U0001d72a\U0001d52c\uff2f\u0be6\u0030\u24c4\u0a66\u2134\U0001d6b6\U0001d7b8\u0ed0\U0001d79e\uff10\u03bf\u043e\u1040\U0001d442\U0001d744\U0001d546\U0001d5c8\U0001d64a\U0001d664\U0001d67e\u004f\U0001d7ce\u0e50\U0001d5e2\u0555\u2d54\u0c02\U0001d7d8\u0c82\U0001d45c\u24de\U0001d560\U0001d7e2\U0001d764\u0ae6\U0001d490\u0ce6\u0b66\U0001d4aa\u006f\u24ea\u2070\U0001d4de\U0001d476\u00ba\U0001d4f8\U0001d6d0\U0001d57a\U0001d5fc\U0001d77e
    1\U0001d408\U0001d456\U0001d591\U0001d610\u2112\u0399\u24db\u0322\u13a5\U0001d526\u03b9\U0001d43c\U0001d73e\U0001d5c5\U0001d644\u004c\U0001d7d9\U0001d4db\U0001d55a\U0001d75e\u2460\U0001d7ed\u006c\U0001d470\U0001d5f9\U0001d678\u24be\U0001d40b\U0001d58e\uff11\U0001d613\u0196\U0001d6a4\U0001d529\u0131\U0001d6b0\U0001d7b2\u2139\U0001d43f\u1fbe\u04c0\U0001d5c2\u0345\U0001d647\uff49\u24d8\U0001d55d\u13de\U0001d473\U0001d5f6\U0001d67b\u2081\U0001d704\u0406\U0001d48d\u2110\U0001d695\U0001d4d8\U0001d422\U0001d724\u0328\U0001d5ab\U0001d62a\uff2c\u00b9\u24c1\U0001d540\u2148\uff4c\U0001d7cf\u0456\U0001d5df\U0001d65e\u02e1\u2160\U0001d7e3\u0069\u216c\u2170\U0001d4f5\U0001d574\U0001d7f7\U0001d778\u217c\u2780\U0001d48a\U0001d50f\u2113\U0001d692\U0001d798\U0001d425\U0001d5a8\u2111\U0001d62d\u0031\U0001d4be\U0001d543\u0049\U0001d6ca\U0001d459\U0001d5dc\U0001d661\u0269\U0001d6ea\u2071\uff29\u2373\U0001d4f2\U0001d577\u0130
    2\u2781\u2461\u2082\U0001d7e4\U0001d7ee\U0001d7d0\uff12\U0001d7f8\u0032\U0001d7da\u00b2\u14bf
    3\u2083\u2782\U0001d409\u0408\U0001d48b\u148d\U0001d58f\U0001d611\u24d9\U0001d693\u0417\u0545\U0001d55b\U0001d423\U0001d4a5\U0001d527\U0001d5a9\u13ab\uff2a\u03f3\u00b3\u02b2\u0437\u0575\U0001d43d\u24bf\U0001d541\U0001d5c3\u004a\U0001d645\u0033\u2149\U0001d50d\uff4a\U0001d7d1\U0001d679\U0001d457\U0001d4d9\u0458\U0001d7db\U0001d5dd\u025c\U0001d65f\u2462\U0001d7e5\u13e7\u006a\uff13\U0001d7ef\U0001d471\U0001d4f3\U0001d575\U0001d4bf\U0001d5f7\U0001d7f9\U0001d62b
    4\u2783\u2084\U0001d7e6\u0034\u2463\u13ce\U0001d7f0\U0001d7d2\uff14\U0001d7fa\U0001d7dc\u2074
    5\U0001d598\U0001d600\U0001d682\u2085\u2784\u0053\u02e2\U0001d412\uff15\U0001d494\U0001d516\u0405\U0001d61a\U0001d69c\U0001d42c\U0001d4ae\U0001d530\uff33\U0001d5b2\u0035\U0001d634\u24c8\u01bd\u01bc\U0001d446\U0001d4c8\U0001d54a\U0001d5cc\U0001d64e\U0001d7d3\U0001d4e2\u13d5\u13da\U0001d7dd\u2464\U0001d460\u24e2\U0001d564\U0001d7e7\U0001d5e6\U0001d668\uff53\U0001d7f1\u0073\u2075\u0455\U0001d7fb\U0001d47a\U0001d4fc\u017f\U0001d57e
    6\u0431\u2785\u2086\U0001d7e8\u0036\u2076\u0411\U0001d7f2\U0001d7d4\uff16\u2465\U0001d7fc\U0001d7de
    7\u0037\u2087\u2786\U0001d7e9\u2466\u2077\U0001d7f3\U0001d7d5\uff17\U0001d7fd\U0001d7df
    8\U0001d7e0\u0b03\u0222\u2467\u2787\u09ea\u2088\U0001d7ea\uff18\u0223\U0001d7f4\U0001d7d6\u0038\u0a6a\u2078\U0001d7fe
    9\U0001d7e1\u2468\u2079\u0a67\u2089\u2788\U0001d7eb\u09ed\u0039\U0001d7f5\U0001d7d7\u0b68\uff19\U0001d7ff
    '''.split())) == confuse(
        u'0' * len('................................................................................')
        +
        u'1' * len('...............................................................................................................')
        +
        u'2' * len('.............')
        +
        u'3' * len('.........................................................')
        +
        u'4' * len('.............')
        +
        u'5' * len('....................................................')
        +
        u'6' * len('..............')
        +
        u'7' * len('............')
        +
        u'8' * len('.................')
        +
        u'9' * len('...............')
        ))
    pass
Пример #6
0
def test():
    '''
    Small smoke test to make sure this module is not broken.
    '''
    assert unilen(u'\U0010fffd') == 1
    assert len(u'Hello, world!') == unilen(u'Hello, world!')
    assert uniord(u'\U0010fffd') == 0x10fffd
    assert uniord(u'H') == ord(u'H')
    assert unichr(0x10fffd) == u'\U0010fffd'
    assert unichr(ord(u'H')) == u'H'
    assert [ch for ch in unichars(u'H\U0010fffd')] == ['H', u'\U0010fffd']
    assert confuse(u'Hello, world!', ['all'],
                   True) == confuse(u'he110, w0r1d!', ['all'], True)
    assert confuse(u'Sergey Brin') == confuse(
        u'5e\N{GREEK SMALL LETTER GAMMA}g\N{GREEK SMALL LETTER EPSILON}\N{GREEK SMALL LETTER UPSILON} \N{GREEK CAPITAL LETTER BETA}r1\N{GREEK CAPITAL LETTER NU}'
    )
    assert confuse(u'He\N{LATIN SMALL LETTER SHARP S}e') == confuse(u'Hesse')
    assert confuse(
        u'\N{GREEK CAPITAL LETTER KAPPA}\N{GREEK SMALL LETTER NU}\N{GREEK SMALL LETTER OMEGA}\N{GREEK SMALL LETTER SIGMA}\N{GREEK SMALL LETTER OMICRON WITH TONOS}\N{GREEK SMALL LETTER FINAL SIGMA}'
    ) == confuse(u'Kv\N{OHM SIGN}co\N{COMBINING ACUTE ACCENT}c')
    assert confuse(u'\N{LATIN SMALL LETTER I}') == confuse(
        u'\N{LATIN CAPITAL LETTER I}')
    assert confuse(u'\N{LATIN SMALL LETTER I}\N{COMBINING DOT ABOVE}'
                   ) == confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}') == confuse(
        u'\N{LATIN CAPITAL LETTER I}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}'
                   ) == confuse(u'\N{LATIN SMALL LETTER I}')
    assert confuse(
        u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}') == confuse(
            u'\N{LATIN SMALL LETTER I}\N{COMBINING DOT ABOVE}')
    assert confuse(
        u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}') == confuse(
            u'\N{LATIN CAPITAL LETTER I}\N{COMBINING DOT ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER DOTLESS I}\N{COMBINING DOT ABOVE}'
                   ) == confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER I}\N{COMBINING DOT ABOVE}'
                   ) == confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}') == confuse(
        u'\N{DIGIT ONE}\N{COMBINING DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER O WITH HORN}') == confuse(
        u'\N{DIGIT ZERO}\N{COMBINING HORN}')
    assert confuse(u'\N{LATIN SMALL LETTER O WITH HORN}') == confuse(
        u'\N{DIGIT ZERO}\N{COMBINING HORN}')
    assert confuse(u'\N{LATIN SMALL LETTER I}') == confuse(
        u'\N{LATIN SMALL LETTER I}\N{COMBINING DOT ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER I}') == confuse(
        u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER I WITH DOT ABOVE}') == confuse(
        u'\N{DIGIT ONE}')
    assert confuse(u'\N{LATIN CAPITAL LETTER O WITH HORN}') == confuse(
        u'\N{LATIN CAPITAL LETTER O}\N{SPACE}\N{COMBINING COMMA ABOVE}')
    assert confuse(u'\N{LATIN SMALL LETTER O WITH HORN}') == confuse(
        u'\N{LATIN CAPITAL LETTER O}\N{SPACE}\N{COMBINING COMMA ABOVE}')

    # NOTE: this is a weak bidi homograph for "i love you"
    assert confuse(u'ڸ٥ﻻ ﻉ√٥ﺎ ٱ') == confuse(
        u'\u06b8\u0665\ufefb \ufec9\u221a\u0665\ufe8e \u0671')
    assert confuse(u'\u06b8\u0665\u0644\u0627 \u0639\u221a\u0665\u0627 \u0671'
                   ) == confuse(u'ڸ٥ﻻ ﻉ√٥ﺎ ٱ')
    assert (confuse(u''.join(u'''
    0\u09e6\u2080\u0d02\u0585\u3007\U0001d70a\U0001d5ae\u1d0f\U0001d40e\u1810\U0001d512\U0001d7f6\U0001d594\U0001d616\U0001d698\u0966\u101d\U0001d6f0\u039f\u041e\u0d20\U0001d7ec\uff4f\u0c66\U0001d630\U0001d428\U0001d72a\U0001d52c\uff2f\u0be6\u0030\u24c4\u0a66\u2134\U0001d6b6\U0001d7b8\u0ed0\U0001d79e\uff10\u03bf\u043e\u1040\U0001d442\U0001d744\U0001d546\U0001d5c8\U0001d64a\U0001d664\U0001d67e\u004f\U0001d7ce\u0e50\U0001d5e2\u0555\u2d54\u0c02\U0001d7d8\u0c82\U0001d45c\u24de\U0001d560\U0001d7e2\U0001d764\u0ae6\U0001d490\u0ce6\u0b66\U0001d4aa\u006f\u24ea\u2070\U0001d4de\U0001d476\u00ba\U0001d4f8\U0001d6d0\U0001d57a\U0001d5fc\U0001d77e
    1\U0001d408\U0001d456\U0001d591\U0001d610\u2112\u0399\u24db\u0322\u13a5\U0001d526\u03b9\U0001d43c\U0001d73e\U0001d5c5\U0001d644\u004c\U0001d7d9\U0001d4db\U0001d55a\U0001d75e\u2460\U0001d7ed\u006c\U0001d470\U0001d5f9\U0001d678\u24be\U0001d40b\U0001d58e\uff11\U0001d613\u0196\U0001d6a4\U0001d529\u0131\U0001d6b0\U0001d7b2\u2139\U0001d43f\u1fbe\u04c0\U0001d5c2\u0345\U0001d647\uff49\u24d8\U0001d55d\u13de\U0001d473\U0001d5f6\U0001d67b\u2081\U0001d704\u0406\U0001d48d\u2110\U0001d695\U0001d4d8\U0001d422\U0001d724\u0328\U0001d5ab\U0001d62a\uff2c\u00b9\u24c1\U0001d540\u2148\uff4c\U0001d7cf\u0456\U0001d5df\U0001d65e\u02e1\u2160\U0001d7e3\u0069\u216c\u2170\U0001d4f5\U0001d574\U0001d7f7\U0001d778\u217c\u2780\U0001d48a\U0001d50f\u2113\U0001d692\U0001d798\U0001d425\U0001d5a8\u2111\U0001d62d\u0031\U0001d4be\U0001d543\u0049\U0001d6ca\U0001d459\U0001d5dc\U0001d661\u0269\U0001d6ea\u2071\uff29\u2373\U0001d4f2\U0001d577\u0130
    2\u2781\u2461\u2082\U0001d7e4\U0001d7ee\U0001d7d0\uff12\U0001d7f8\u0032\U0001d7da\u00b2\u14bf
    3\u2083\u2782\U0001d409\u0408\U0001d48b\u148d\U0001d58f\U0001d611\u24d9\U0001d693\u0417\u0545\U0001d55b\U0001d423\U0001d4a5\U0001d527\U0001d5a9\u13ab\uff2a\u03f3\u00b3\u02b2\u0437\u0575\U0001d43d\u24bf\U0001d541\U0001d5c3\u004a\U0001d645\u0033\u2149\U0001d50d\uff4a\U0001d7d1\U0001d679\U0001d457\U0001d4d9\u0458\U0001d7db\U0001d5dd\u025c\U0001d65f\u2462\U0001d7e5\u13e7\u006a\uff13\U0001d7ef\U0001d471\U0001d4f3\U0001d575\U0001d4bf\U0001d5f7\U0001d7f9\U0001d62b
    4\u2783\u2084\U0001d7e6\u0034\u2463\u13ce\U0001d7f0\U0001d7d2\uff14\U0001d7fa\U0001d7dc\u2074
    5\U0001d598\U0001d600\U0001d682\u2085\u2784\u0053\u02e2\U0001d412\uff15\U0001d494\U0001d516\u0405\U0001d61a\U0001d69c\U0001d42c\U0001d4ae\U0001d530\uff33\U0001d5b2\u0035\U0001d634\u24c8\u01bd\u01bc\U0001d446\U0001d4c8\U0001d54a\U0001d5cc\U0001d64e\U0001d7d3\U0001d4e2\u13d5\u13da\U0001d7dd\u2464\U0001d460\u24e2\U0001d564\U0001d7e7\U0001d5e6\U0001d668\uff53\U0001d7f1\u0073\u2075\u0455\U0001d7fb\U0001d47a\U0001d4fc\u017f\U0001d57e
    6\u0431\u2785\u2086\U0001d7e8\u0036\u2076\u0411\U0001d7f2\U0001d7d4\uff16\u2465\U0001d7fc\U0001d7de
    7\u0037\u2087\u2786\U0001d7e9\u2466\u2077\U0001d7f3\U0001d7d5\uff17\U0001d7fd\U0001d7df
    8\U0001d7e0\u0b03\u0222\u2467\u2787\u09ea\u2088\U0001d7ea\uff18\u0223\U0001d7f4\U0001d7d6\u0038\u0a6a\u2078\U0001d7fe
    9\U0001d7e1\u2468\u2079\u0a67\u2089\u2788\U0001d7eb\u09ed\u0039\U0001d7f5\U0001d7d7\u0b68\uff19\U0001d7ff
    '''.split())) == confuse(u'0' * len(
        '................................................................................'
    ) + u'1' * len(
        '...............................................................................................................'
    ) + u'2' * len('.............') + u'3' * len(
        '.........................................................'
    ) + u'4' * len('.............') + u'5' * len(
        '....................................................') +
                             u'6' * len('..............') +
                             u'7' * len('............') +
                             u'8' * len('.................') +
                             u'9' * len('...............')))
    pass