I am using Python 3 and I know all about hex, int, chr, ord, '\uxxxx' escape and '\U00xxxxxx' escape and Unicode has 1114111 codepoints...
How can I check if a Unicode codepoint is valid? That is, it is unambiguously mapped to a authoritatively defined character.
For example, codepoint 720 is valid; it is 0x2d0 in hex, and U+02D0 points to ː:
In [135]: hex(720)
Out[135]: '0x2d0'
In [136]: '\u02d0'
Out[136]: 'ː'
And 888 is not valid:
In [137]: hex(888)
Out[137]: '0x378'
In [138]: '\u0378'
Out[138]: '\u0378'
And 127744 is valid:
In [139]: chr(127744)
Out[139]: ''
And 0xe0000 is invalid:
In [140]: '\U000e0000'
Out[140]: '\U000e0000'
I have come up with a rather hacky solution: if a codepoint is valid, trying to convert it to a character will either result in the decoded character or the '\xhh' escape sequence, else it will return the undecoded escape sequence exactly same as original, I can check the return value of chr and check if it starts with '\u' or '\U'...
Now is the hacky part, chr doesn't decode invalid codepoints but it doesn't raise exceptions either, and the escape sequences will have length of 1 since they are treated as a single character, I have to repr the return value and check the results...
I have used this method to identify all invalid codepoints:
In [130]: invalid = []
In [131]: for i in range(1114112):
...: if any(f'{chr(i)!r}'.startswith(j) for j in ("'\\U", "'\\u")):
...: invalid.append(i)
In [132]: from pathlib import Path
In [133]: invalid = [(hex(i).removeprefix('0x'), i) for i in invalid]
In [134]: Path('D:/invalid_unicode.txt').write_text(',\n'.join(map(repr, invalid)))
Out[134]: 18574537
Can anyone offer a better solution?