summaryrefslogtreecommitdiffstats
path: root/Lib/base64.py
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2013-10-02 14:43:22 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2013-10-02 14:43:22 (GMT)
commitfdf239a855c82bc20df157815de947867aa2648e (patch)
tree05995514fc9cbb3283c5bdd2586982baebc3286b /Lib/base64.py
parent73c6ee00805729919f98d4f2dbe27e16c54b4db2 (diff)
downloadcpython-fdf239a855c82bc20df157815de947867aa2648e.zip
cpython-fdf239a855c82bc20df157815de947867aa2648e.tar.gz
cpython-fdf239a855c82bc20df157815de947867aa2648e.tar.bz2
Close #17839: support bytes-like objects in base64 module
This mostly affected the encodebytes and decodebytes function (which are used by base64_codec) Also added a test to ensure all bytes-bytes codecs can handle memoryview input and tests for handling of multidimensional and non-bytes format input in the modern base64 API.
Diffstat (limited to 'Lib/base64.py')
-rwxr-xr-xLib/base64.py40
1 files changed, 24 insertions, 16 deletions
diff --git a/Lib/base64.py b/Lib/base64.py
index 9c15752..0a93f2e 100755
--- a/Lib/base64.py
+++ b/Lib/base64.py
@@ -35,11 +35,13 @@ def _bytes_from_decode_data(s):
return s.encode('ascii')
except UnicodeEncodeError:
raise ValueError('string argument should contain only ASCII characters')
- elif isinstance(s, bytes_types):
+ if isinstance(s, bytes_types):
return s
- else:
- raise TypeError("argument should be bytes or ASCII string, not %s" % s.__class__.__name__)
-
+ try:
+ return memoryview(s).tobytes()
+ except TypeError:
+ raise TypeError("argument should be a bytes-like object or ASCII "
+ "string, not %r" % s.__class__.__name__) from None
# Base64 encoding/decoding uses binascii
@@ -54,14 +56,9 @@ def b64encode(s, altchars=None):
The encoded byte string is returned.
"""
- if not isinstance(s, bytes_types):
- raise TypeError("expected bytes, not %s" % s.__class__.__name__)
# Strip off the trailing newline
encoded = binascii.b2a_base64(s)[:-1]
if altchars is not None:
- if not isinstance(altchars, bytes_types):
- raise TypeError("expected bytes, not %s"
- % altchars.__class__.__name__)
assert len(altchars) == 2, repr(altchars)
return encoded.translate(bytes.maketrans(b'+/', altchars))
return encoded
@@ -149,7 +146,7 @@ def b32encode(s):
s is the byte string to encode. The encoded byte string is returned.
"""
if not isinstance(s, bytes_types):
- raise TypeError("expected bytes, not %s" % s.__class__.__name__)
+ s = memoryview(s).tobytes()
leftover = len(s) % 5
# Pad the last quantum with zero bits if necessary
if leftover:
@@ -250,8 +247,6 @@ def b16encode(s):
s is the byte string to encode. The encoded byte string is returned.
"""
- if not isinstance(s, bytes_types):
- raise TypeError("expected bytes, not %s" % s.__class__.__name__)
return binascii.hexlify(s).upper()
@@ -306,12 +301,26 @@ def decode(input, output):
s = binascii.a2b_base64(line)
output.write(s)
+def _input_type_check(s):
+ try:
+ m = memoryview(s)
+ except TypeError as err:
+ msg = "expected bytes-like object, not %s" % s.__class__.__name__
+ raise TypeError(msg) from err
+ if m.format not in ('c', 'b', 'B'):
+ msg = ("expected single byte elements, not %r from %s" %
+ (m.format, s.__class__.__name__))
+ raise TypeError(msg)
+ if m.ndim != 1:
+ msg = ("expected 1-D data, not %d-D data from %s" %
+ (m.ndim, s.__class__.__name__))
+ raise TypeError(msg)
+
def encodebytes(s):
"""Encode a bytestring into a bytestring containing multiple lines
of base-64 data."""
- if not isinstance(s, bytes_types):
- raise TypeError("expected bytes, not %s" % s.__class__.__name__)
+ _input_type_check(s)
pieces = []
for i in range(0, len(s), MAXBINSIZE):
chunk = s[i : i + MAXBINSIZE]
@@ -328,8 +337,7 @@ def encodestring(s):
def decodebytes(s):
"""Decode a bytestring of base-64 data into a bytestring."""
- if not isinstance(s, bytes_types):
- raise TypeError("expected bytes, not %s" % s.__class__.__name__)
+ _input_type_check(s)
return binascii.a2b_base64(s)
def decodestring(s):