Plain is headed towards 1.0! Subscribe for development updates →

 1import base64
 2import unicodedata
 3from binascii import Error as BinasciiError
 4
 5from plain.internal import internalcode
 6
 7
 8@internalcode
 9def urlsafe_base64_encode(s):
10    """
11    Encode a bytestring to a base64 string for use in URLs. Strip any trailing
12    equal signs.
13    """
14    return base64.urlsafe_b64encode(s).rstrip(b"\n=").decode("ascii")
15
16
17@internalcode
18def urlsafe_base64_decode(s):
19    """
20    Decode a base64 encoded string. Add back any trailing equal signs that
21    might have been stripped.
22    """
23    s = s.encode()
24    try:
25        return base64.urlsafe_b64decode(s.ljust(len(s) + len(s) % 4, b"="))
26    except (LookupError, BinasciiError) as e:
27        raise ValueError(e)
28
29
30@internalcode
31def unicode_ci_compare(s1, s2):
32    """
33    Perform case-insensitive comparison of two identifiers, using the
34    recommended algorithm from Unicode Technical Report 36, section
35    2.11.2(B)(2).
36    """
37    return (
38        unicodedata.normalize("NFKC", s1).casefold()
39        == unicodedata.normalize("NFKC", s2).casefold()
40    )