1010import struct
1111import binascii
1212
13-
1413__all__ = [
1514 # Legacy interface exports traditional RFC 1521 Base64 encodings
1615 "encode" ,
3534 "urlsafe_b64decode" ,
3635]
3736
38-
3937bytes_types = (bytes , bytearray ) # Types acceptable as binary data
4038
4139
@@ -52,6 +50,25 @@ def _bytes_from_decode_data(s):
5250 raise TypeError ("argument should be bytes or ASCII string, not %s" % s .__class__ .__name__ )
5351
5452
53+ def _maketrans (f , t ):
54+ """Re-implement bytes.maketrans() as there is no such function in micropython"""
55+ if len (f ) != len (t ):
56+ raise ValueError ("maketrans arguments must have same length" )
57+ translation_table = dict (zip (f , t ))
58+ return translation_table
59+
60+
61+ def _translate (input_bytes , trans_table ):
62+ """Re-implement bytes.translate() as there is no such function in micropython"""
63+ result = bytearray ()
64+
65+ for byte in input_bytes :
66+ translated_byte = trans_table .get (byte , byte )
67+ result .append (translated_byte )
68+
69+ return bytes (result )
70+
71+
5572# Base64 encoding/decoding uses binascii
5673
5774
@@ -73,7 +90,7 @@ def b64encode(s, altchars=None):
7390 if not isinstance (altchars , bytes_types ):
7491 raise TypeError ("expected bytes, not %s" % altchars .__class__ .__name__ )
7592 assert len (altchars ) == 2 , repr (altchars )
76- return encoded . translate ( bytes . maketrans (b"+/" , altchars ))
93+ encoded = _translate ( encoded , _maketrans (b"+/" , altchars ))
7794 return encoded
7895
7996
@@ -95,7 +112,7 @@ def b64decode(s, altchars=None, validate=False):
95112 if altchars is not None :
96113 altchars = _bytes_from_decode_data (altchars )
97114 assert len (altchars ) == 2 , repr (altchars )
98- s = s . translate ( bytes . maketrans (altchars , b"+/" ))
115+ s = _translate ( s , _maketrans (altchars , b"+/" ))
99116 if validate and not re .match (b"^[A-Za-z0-9+/]*=*$" , s ):
100117 raise binascii .Error ("Non-base64 digit found" )
101118 return binascii .a2b_base64 (s )
@@ -120,8 +137,8 @@ def standard_b64decode(s):
120137 return b64decode (s )
121138
122139
123- # _urlsafe_encode_translation = bytes.maketrans (b'+/', b'-_')
124- # _urlsafe_decode_translation = bytes.maketrans (b'-_', b'+/')
140+ # _urlsafe_encode_translation = _maketrans (b'+/', b'-_')
141+ # _urlsafe_decode_translation = _maketrans (b'-_', b'+/')
125142
126143
127144def urlsafe_b64encode (s ):
@@ -132,7 +149,7 @@ def urlsafe_b64encode(s):
132149 '/'.
133150 """
134151 # return b64encode(s).translate(_urlsafe_encode_translation)
135- raise NotImplementedError ( )
152+ return b64encode ( s , b"-_" ). rstrip ( b' \n ' )
136153
137154
138155def urlsafe_b64decode (s ):
@@ -210,7 +227,7 @@ def b32encode(s):
210227 # leftover bit of c1 and tack it onto c2. Then we take the 2 leftover
211228 # bits of c2 and tack them onto c3. The shifts and masks are intended
212229 # to give us values of exactly 5 bits in width.
213- c1 , c2 , c3 = struct .unpack ("!HHB" , s [i * 5 : (i + 1 ) * 5 ])
230+ c1 , c2 , c3 = struct .unpack ("!HHB" , s [i * 5 : (i + 1 ) * 5 ])
214231 c2 += (c1 & 1 ) << 16 # 17 bits wide
215232 c3 += (c2 & 3 ) << 8 # 10 bits wide
216233 encoded += bytes (
@@ -266,7 +283,7 @@ def b32decode(s, casefold=False, map01=None):
266283 if map01 is not None :
267284 map01 = _bytes_from_decode_data (map01 )
268285 assert len (map01 ) == 1 , repr (map01 )
269- s = s . translate ( bytes . maketrans (b"01" , b"O" + map01 ))
286+ s = _translate ( s , _maketrans (b"01" , b"O" + map01 ))
270287 if casefold :
271288 s = s .upper ()
272289 # Strip off pad characters from the right. We need to count the pad
@@ -383,7 +400,7 @@ def encodebytes(s):
383400 raise TypeError ("expected bytes, not %s" % s .__class__ .__name__ )
384401 pieces = []
385402 for i in range (0 , len (s ), MAXBINSIZE ):
386- chunk = s [i : i + MAXBINSIZE ]
403+ chunk = s [i : i + MAXBINSIZE ]
387404 pieces .append (binascii .b2a_base64 (chunk ))
388405 return b"" .join (pieces )
389406
0 commit comments