Index: Modules/binascii.c =================================================================== --- Modules/binascii.c (revision 85127) +++ Modules/binascii.c (working copy) @@ -188,19 +188,21 @@ static PyObject * binascii_a2b_uu(PyObject *self, PyObject *args) { - Py_buffer pascii; - unsigned char *ascii_data, *bin_data; + PyObject *pascii; + Py_UNICODE *ascii_data; + unsigned char *bin_data; int leftbits = 0; - unsigned char this_ch; + Py_UNICODE this_ch; unsigned int leftchar = 0; PyObject *rv; Py_ssize_t ascii_len, bin_len; - if ( !PyArg_ParseTuple(args, "y*:a2b_uu", &pascii) ) + if ( !PyArg_ParseTuple(args, "U:a2b_uu", &pascii) ) return NULL; - ascii_data = pascii.buf; - ascii_len = pascii.len; + ascii_data = PyUnicode_AS_UNICODE(pascii); + ascii_len = PyUnicode_GET_SIZE(pascii); + assert(ascii_len >= 0); /* First byte: binary data length (in bytes) */ @@ -209,13 +211,12 @@ /* Allocate the buffer */ if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) { - PyBuffer_Release(&pascii); return NULL; } bin_data = (unsigned char *)PyBytes_AS_STRING(rv); for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) { - /* XXX is it really best to add NULs if there's no more data */ + /* XXX is it really best to add NULLs if there's no more data */ this_ch = (ascii_len > 0) ? *ascii_data : 0; if ( this_ch == '\n' || this_ch == '\r' || ascii_len <= 0) { /* @@ -231,7 +232,6 @@ */ if ( this_ch < ' ' || this_ch > (' ' + 64)) { PyErr_SetString(Error, "Illegal char"); - PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } @@ -260,12 +260,10 @@ if ( this_ch != ' ' && this_ch != ' '+64 && this_ch != '\n' && this_ch != '\r' ) { PyErr_SetString(Error, "Trailing garbage"); - PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } } - PyBuffer_Release(&pascii); return rv; } @@ -275,9 +273,10 @@ binascii_b2a_uu(PyObject *self, PyObject *args) { Py_buffer pbin; - unsigned char *ascii_data, *bin_data; + Py_UNICODE *ascii_data; + unsigned char *bin_data; int leftbits = 0; - unsigned char this_ch; + Py_UNICODE this_ch; unsigned int leftchar = 0; PyObject *rv; Py_ssize_t bin_len; @@ -293,12 +292,12 @@ return NULL; } - /* We're lazy and allocate to much (fixed up later) */ - if ( (rv=PyBytes_FromStringAndSize(NULL, 2 + (bin_len+2)/3*4)) == NULL ) { + /* We're lazy and allocate too much (fixed up later) */ + if ( (rv=PyUnicode_FromStringAndSize(NULL, 2 + (bin_len+2)/3*4)) == NULL ) { PyBuffer_Release(&pbin); return NULL; } - ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); + ascii_data = PyUnicode_AS_UNICODE(rv); /* Store the length */ *ascii_data++ = ' ' + (bin_len & 077); @@ -320,9 +319,9 @@ } *ascii_data++ = '\n'; /* Append a courtesy newline */ - if (_PyBytes_Resize(&rv, + if (PyUnicode_Resize(&rv, (ascii_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { + (Py_UNICODE *)PyUnicode_AS_UNICODE(rv))) < 0) { Py_DECREF(rv); rv = NULL; } @@ -332,7 +331,7 @@ static int -binascii_find_valid(unsigned char *s, Py_ssize_t slen, int num) +binascii_find_valid(Py_UNICODE *s, Py_ssize_t slen, int num) { /* Finds & returns the (num+1)th ** valid character for base64, or -1 if none. @@ -342,7 +341,7 @@ unsigned char c, b64val; while ((slen > 0) && (ret == -1)) { - c = *s; + c = (unsigned char) *s; b64val = table_a2b_base64[c & 0x7f]; if ( ((c <= 0x7f) && (b64val != (unsigned char)-1)) ) { if (num == 0) @@ -361,8 +360,9 @@ static PyObject * binascii_a2b_base64(PyObject *self, PyObject *args) { - Py_buffer pascii; - unsigned char *ascii_data, *bin_data; + PyObject *pascii; + Py_UNICODE *ascii_data; + unsigned char *bin_data; int leftbits = 0; unsigned char this_ch; unsigned int leftchar = 0; @@ -370,15 +370,14 @@ Py_ssize_t ascii_len, bin_len; int quad_pos = 0; - if ( !PyArg_ParseTuple(args, "y*:a2b_base64", &pascii) ) + if ( !PyArg_ParseTuple(args, "U:a2b_base64", &pascii) ) return NULL; - ascii_data = pascii.buf; - ascii_len = pascii.len; + ascii_data = PyUnicode_AS_UNICODE(pascii); + ascii_len = PyUnicode_GET_SIZE(pascii); assert(ascii_len >= 0); if (ascii_len > PY_SSIZE_T_MAX - 3) { - PyBuffer_Release(&pascii); return PyErr_NoMemory(); } @@ -386,14 +385,13 @@ /* Allocate the buffer */ if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) { - PyBuffer_Release(&pascii); return NULL; } bin_data = (unsigned char *)PyBytes_AS_STRING(rv); bin_len = 0; for( ; ascii_len > 0; ascii_len--, ascii_data++) { - this_ch = *ascii_data; + this_ch = (unsigned char) *ascii_data; if (this_ch > 0x7f || this_ch == '\r' || this_ch == '\n' || this_ch == ' ') @@ -441,7 +439,6 @@ } if (leftbits != 0) { - PyBuffer_Release(&pascii); PyErr_SetString(Error, "Incorrect padding"); Py_DECREF(rv); return NULL; @@ -461,7 +458,6 @@ Py_DECREF(rv); rv = PyBytes_FromStringAndSize("", 0); } - PyBuffer_Release(&pascii); return rv; } @@ -471,9 +467,10 @@ binascii_b2a_base64(PyObject *self, PyObject *args) { Py_buffer pbuf; - unsigned char *ascii_data, *bin_data; + Py_UNICODE *ascii_data; + unsigned char *bin_data; int leftbits = 0; - unsigned char this_ch; + Py_UNICODE this_ch; unsigned int leftchar = 0; PyObject *rv; Py_ssize_t bin_len; @@ -494,11 +491,11 @@ /* We're lazy and allocate too much (fixed up later). "+3" leaves room for up to two pad characters and a trailing newline. Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */ - if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) { + if ( (rv=PyUnicode_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) { PyBuffer_Release(&pbuf); return NULL; } - ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); + ascii_data = PyUnicode_AS_UNICODE(rv); for( ; bin_len > 0 ; bin_len--, bin_data++ ) { /* Shift the data into our buffer */ @@ -522,9 +519,9 @@ } *ascii_data++ = '\n'; /* Append a courtesy newline */ - if (_PyBytes_Resize(&rv, + if (PyUnicode_Resize(&rv, (ascii_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { + (Py_UNICODE *)PyUnicode_AS_UNICODE(rv))) < 0) { Py_DECREF(rv); rv = NULL; } @@ -537,24 +534,24 @@ static PyObject * binascii_a2b_hqx(PyObject *self, PyObject *args) { - Py_buffer pascii; - unsigned char *ascii_data, *bin_data; + PyObject *pascii; + Py_UNICODE *ascii_data; + unsigned char *bin_data; int leftbits = 0; - unsigned char this_ch; + Py_UNICODE this_ch; unsigned int leftchar = 0; PyObject *rv; Py_ssize_t len; int done = 0; - if ( !PyArg_ParseTuple(args, "y*:a2b_hqx", &pascii) ) + if ( !PyArg_ParseTuple(args, "U:a2b_hqx", &pascii) ) return NULL; - ascii_data = pascii.buf; - len = pascii.len; + ascii_data = PyUnicode_AS_UNICODE(pascii); + len = PyUnicode_GET_SIZE(pascii); assert(len >= 0); if (len > PY_SSIZE_T_MAX - 2) { - PyBuffer_Release(&pascii); return PyErr_NoMemory(); } @@ -562,7 +559,6 @@ Add two to the initial length to prevent interning which would preclude subsequent resizing. */ if ( (rv=PyBytes_FromStringAndSize(NULL, len+2)) == NULL ) { - PyBuffer_Release(&pascii); return NULL; } bin_data = (unsigned char *)PyBytes_AS_STRING(rv); @@ -574,7 +570,6 @@ continue; if ( this_ch == FAIL ) { PyErr_SetString(Error, "Illegal char"); - PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } @@ -597,7 +592,6 @@ if ( leftbits && !done ) { PyErr_SetString(Incomplete, "String has incomplete number of bytes"); - PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } @@ -609,12 +603,10 @@ } if (rv) { PyObject *rrv = Py_BuildValue("Oi", rv, done); - PyBuffer_Release(&pascii); Py_DECREF(rv); return rrv; } - PyBuffer_Release(&pascii); return NULL; } @@ -688,9 +680,10 @@ binascii_b2a_hqx(PyObject *self, PyObject *args) { Py_buffer pbin; - unsigned char *ascii_data, *bin_data; + Py_UNICODE *ascii_data; + unsigned char *bin_data; int leftbits = 0; - unsigned char this_ch; + Py_UNICODE this_ch; unsigned int leftchar = 0; PyObject *rv; Py_ssize_t len; @@ -708,11 +701,11 @@ } /* Allocate a buffer that is at least large enough */ - if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) { + if ( (rv=PyUnicode_FromStringAndSize(NULL, len*2+2)) == NULL ) { PyBuffer_Release(&pbin); return NULL; } - ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); + ascii_data = PyUnicode_AS_UNICODE(rv); for( ; len > 0 ; len--, bin_data++ ) { /* Shift into our buffer, and output any 6bits ready */ @@ -729,9 +722,9 @@ leftchar <<= (6-leftbits); *ascii_data++ = table_b2a_hqx[leftchar & 0x3f]; } - if (_PyBytes_Resize(&rv, + if (PyUnicode_Resize(&rv, (ascii_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { + (Py_UNICODE *)PyUnicode_AS_UNICODE(rv))) < 0) { Py_DECREF(rv); rv = NULL; } @@ -1051,43 +1044,43 @@ static PyObject * binascii_hexlify(PyObject *self, PyObject *args) { - Py_buffer parg; - char* argbuf; - Py_ssize_t arglen; - PyObject *retval; - char* retbuf; + Py_buffer pbin; + Py_UNICODE *ascii_data; + unsigned char *bin_data; + Py_ssize_t bin_len; + PyObject *rv; Py_ssize_t i, j; - if (!PyArg_ParseTuple(args, "y*:b2a_hex", &parg)) + if (!PyArg_ParseTuple(args, "y*:b2a_hex", &pbin)) return NULL; - argbuf = parg.buf; - arglen = parg.len; + bin_data = pbin.buf; + bin_len = pbin.len; - assert(arglen >= 0); - if (arglen > PY_SSIZE_T_MAX / 2) { - PyBuffer_Release(&parg); + assert(bin_len >= 0); + if (bin_len > PY_SSIZE_T_MAX / 2) { + PyBuffer_Release(&pbin); return PyErr_NoMemory(); } - retval = PyBytes_FromStringAndSize(NULL, arglen*2); - if (!retval) { - PyBuffer_Release(&parg); + rv = PyUnicode_FromStringAndSize(NULL, bin_len*2); + if (!rv) { + PyBuffer_Release(&pbin); return NULL; } - retbuf = PyBytes_AS_STRING(retval); + ascii_data = PyUnicode_AS_UNICODE(rv); - /* make hex version of string, taken from shamodule.c */ - for (i=j=0; i < arglen; i++) { + /* make hex version of string, taken from sha1module.c */ + for (i=j=0; i < bin_len; i++) { char c; - c = (argbuf[i] >> 4) & 0xf; + c = (bin_data[i] >> 4) & 0xf; c = (c>9) ? c+'a'-10 : c + '0'; - retbuf[j++] = c; - c = argbuf[i] & 0xf; + ascii_data[j++] = c; + c = bin_data[i] & 0xf; c = (c>9) ? c+'a'-10 : c + '0'; - retbuf[j++] = c; + ascii_data[j++] = c; } - PyBuffer_Release(&parg); - return retval; + PyBuffer_Release(&pbin); + return rv; } PyDoc_STRVAR(doc_hexlify, @@ -1114,54 +1107,48 @@ static PyObject * binascii_unhexlify(PyObject *self, PyObject *args) { - Py_buffer parg; - char* argbuf; - Py_ssize_t arglen; - PyObject *retval; - char* retbuf; + PyObject *pascii; + Py_UNICODE *ascii_data; + unsigned char *bin_data; + PyObject *rv; + Py_ssize_t ascii_len; Py_ssize_t i, j; - if (!PyArg_ParseTuple(args, "y*:a2b_hex", &parg)) + if ( !PyArg_ParseTuple(args, "U:a2b_uu", &pascii) ) return NULL; - argbuf = parg.buf; - arglen = parg.len; - assert(arglen >= 0); + ascii_data = PyUnicode_AS_UNICODE(pascii); + ascii_len = PyUnicode_GET_SIZE(pascii); + assert(ascii_len >= 0); + /* XXX What should we do about strings with an odd length? Should * we add an implicit leading zero, or a trailing zero? For now, * raise an exception. */ - if (arglen % 2) { - PyBuffer_Release(&parg); + if (ascii_len % 2) { PyErr_SetString(Error, "Odd-length string"); return NULL; } - retval = PyBytes_FromStringAndSize(NULL, (arglen/2)); - if (!retval) { - PyBuffer_Release(&parg); + rv = PyBytes_FromStringAndSize(NULL, (ascii_len/2)); + if (!rv) { return NULL; } - retbuf = PyBytes_AS_STRING(retval); + bin_data = PyBytes_AS_STRING(rv); - for (i=j=0; i < arglen; i += 2) { - int top = to_int(Py_CHARMASK(argbuf[i])); - int bot = to_int(Py_CHARMASK(argbuf[i+1])); + for (i=j=0; i < ascii_len; i += 2) { + int top = to_int(Py_CHARMASK(ascii_data[i])); + int bot = to_int(Py_CHARMASK(ascii_data[i+1])); if (top == -1 || bot == -1) { PyErr_SetString(Error, "Non-hexadecimal digit found"); - goto finally; + Py_DECREF(rv); + return NULL; } - retbuf[j++] = (top << 4) + bot; + bin_data[j++] = (top << 4) + bot; } - PyBuffer_Release(&parg); - return retval; - - finally: - PyBuffer_Release(&parg); - Py_DECREF(retval); - return NULL; + return rv; } PyDoc_STRVAR(doc_unhexlify, @@ -1192,18 +1179,19 @@ { Py_ssize_t in, out; char ch; - Py_buffer pdata; - unsigned char *data, *odata; + PyObject *pdata; + Py_UNICODE *data; + unsigned char *odata; Py_ssize_t datalen = 0; PyObject *rv; static char *kwlist[] = {"data", "header", NULL}; int header = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|i", kwlist, &pdata, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|i:a2b_qp", kwlist, &pdata, &header)) return NULL; - data = pdata.buf; - datalen = pdata.len; + data = PyUnicode_AS_UNICODE(pdata); + datalen = PyUnicode_GET_SIZE(pdata); /* We allocate the output same size as input, this is overkill. * The previous implementation used calloc() so we'll zero out the @@ -1211,7 +1199,6 @@ */ odata = (unsigned char *) PyMem_Malloc(datalen); if (odata == NULL) { - PyBuffer_Release(&pdata); PyErr_NoMemory(); return NULL; } @@ -1256,17 +1243,15 @@ in++; } else { - odata[out] = data[in]; + odata[out] = (unsigned char) data[in]; in++; out++; } } if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) { - PyBuffer_Release(&pdata); PyMem_Free(odata); return NULL; } - PyBuffer_Release(&pdata); PyMem_Free(odata); return rv; } @@ -1467,7 +1452,7 @@ } } } - if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) { + if ((rv = PyUnicode_FromStringAndSize((char *)odata, out)) == NULL) { PyBuffer_Release(&pdata); PyMem_Free(odata); return NULL; Index: Doc/library/binascii.rst =================================================================== --- Doc/library/binascii.rst (revision 85127) +++ Doc/library/binascii.rst (working copy) @@ -12,7 +12,7 @@ module: binhex The :mod:`binascii` module contains a number of methods to convert between -binary and various ASCII-encoded binary representations. Normally, you will not +binary and various ASCII-encoded representations. Normally, you will not use these functions directly but use wrapper modules like :mod:`uu`, :mod:`base64`, or :mod:`binhex` instead. The :mod:`binascii` module contains low-level functions written in C for greater speed that are used by the @@ -20,8 +20,9 @@ .. note:: - Encoding and decoding functions do not accept Unicode strings. Only bytestring - and bytearray objects can be processed. + All encoding functions accept Unicode strings and return bytestrings, and + all decoding functions accept bytestrings or bytearray objects, and return + Unicode strings. The :mod:`binascii` module defines the following functions: @@ -29,30 +30,42 @@ .. function:: a2b_uu(string) Convert a single line of uuencoded data back to binary and return the binary - data. Lines normally contain 45 (binary) bytes, except for the last line. Line + data. Lines normally contain 45 bytes, except for the last line. Line data may be followed by whitespace. + .. versionchanged:: 3.2 + Accept only Unicode strings as input. + .. function:: b2a_uu(data) Convert binary data to a line of ASCII characters, the return value is the converted line, including a newline char. The length of *data* should be at most 45. + .. versionchanged:: 3.2 + Returns Unicode strings. + .. function:: a2b_base64(string) Convert a block of base64 data back to binary and return the binary data. More than one line may be passed at a time. + .. versionchanged:: 3.2 + Accept only Unicode strings as input. + .. function:: b2a_base64(data) Convert binary data to a line of ASCII characters in base64 coding. The return value is the converted line, including a newline char. The length of *data* should be at most 57 to adhere to the base64 standard. + .. versionchanged:: 3.2 + Returns Unicode strings. + .. function:: a2b_qp(string, header=False) Convert a block of quoted-printable data back to binary and return the binary @@ -60,7 +73,7 @@ *header* is present and true, underscores will be decoded as spaces. .. versionchanged:: 3.2 - Accept only bytestring or bytearray objects as input. + Accept only Unicode strings as input. .. function:: b2a_qp(data, quotetabs=False, istext=True, header=False) @@ -75,14 +88,20 @@ encoded as well; otherwise linefeed conversion might corrupt the binary data stream. + .. versionchanged:: 3.2 + Returns Unicode strings. + .. function:: a2b_hqx(string) Convert binhex4 formatted ASCII data to binary, without doing RLE-decompression. - The string should contain a complete number of binary bytes, or (in case of the + The string should contain a complete number of bytes, or (in case of the last portion of the binhex4 data) have the remaining bits zero. + .. versionchanged:: 3.2 + Accept only Unicode strings as input. + .. function:: rledecode_hqx(data) Perform RLE-decompression on the data, as per the binhex4 standard. The @@ -106,7 +125,10 @@ argument should already be RLE-coded, and have a length divisible by 3 (except possibly the last fragment). + .. versionchanged:: 3.2 + Returns Unicode strings. + .. function:: crc_hqx(data, crc) Compute the binhex4 crc value of *data*, starting with an initial *crc* and @@ -141,6 +163,8 @@ *data* is converted into the corresponding 2-digit hex representation. The resulting string is therefore twice as long as the length of *data*. + .. versionchanged:: 3.2 + Returns Unicode strings. .. function:: a2b_hex(hexstr) unhexlify(hexstr) @@ -151,7 +175,7 @@ :exc:`TypeError` is raised. .. versionchanged:: 3.2 - Accept only bytestring or bytearray objects as input. + Accept only Unicode strings as input. .. exception:: Error Index: Doc/library/base64.rst =================================================================== --- Doc/library/base64.rst (revision 85127) +++ Doc/library/base64.rst (working copy) @@ -26,18 +26,18 @@ Encode a byte string use Base64. - *s* is the string to encode. Optional *altchars* must be a string of at least + *s* is the bytestring to encode. Optional *altchars* must be a string of at least length 2 (additional characters are ignored) which specifies an alternative alphabet for the ``+`` and ``/`` characters. This allows an application to e.g. generate URL or filesystem safe Base64 strings. The default is ``None``, for which the standard Base64 alphabet is used. - The encoded byte string is returned. + The encoded string is returned. .. function:: b64decode(s, altchars=None) - Decode a Base64 encoded byte string. + Decode a Base64 encoded string. *s* is the string to decode. Optional *altchars* must be a string of at least length 2 (additional characters are ignored) which specifies the alternative @@ -55,7 +55,7 @@ .. function:: standard_b64decode(s) - Decode byte string *s* using the standard Base64 alphabet. + Decode string *s* using the standard Base64 alphabet. .. function:: urlsafe_b64encode(s) @@ -67,7 +67,7 @@ .. function:: urlsafe_b64decode(s) - Decode byte string *s* using a URL-safe alphabet, which substitutes ``-`` instead of + Decode string *s* using a URL-safe alphabet, which substitutes ``-`` instead of ``+`` and ``_`` instead of ``/`` in the standard Base64 alphabet. @@ -79,7 +79,7 @@ .. function:: b32decode(s, casefold=False, map01=None) - Decode a Base32 encoded byte string. + Decode a Base32 encoded string. *s* is the string to decode. Optional *casefold* is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default @@ -101,7 +101,7 @@ Encode a byte string using Base16. - *s* is the string to encode. The encoded byte string is returned. + *s* is the byte string to encode. The encoded string is returned. .. function:: b16decode(s, casefold=False) @@ -121,7 +121,7 @@ .. function:: decode(input, output) - Decode the contents of the binary *input* file and write the resulting binary + Decode the contents of the *input* file and write the resulting binary data to the *output* file. *input* and *output* must be :term:`file objects `. *input* will be read until ``input.read()`` returns an empty bytes object. @@ -130,9 +130,9 @@ .. function:: decodebytes(s) decodestring(s) - Decode the bytestring *s*, which must contain one or more lines of base64 + Decode the string *s*, which must contain one or more lines of base64 encoded data, and return a bytestring containing the resulting binary data. - ``decodestring`` is a deprecated alias. + ``decodebytes`` is a deprecated alias. .. function:: encode(input, output) @@ -140,15 +140,15 @@ Encode the contents of the binary *input* file and write the resulting base64 encoded data to the *output* file. *input* and *output* must be :term:`file objects `. *input* will be read until ``input.read()`` returns - an empty bytes object. :func:`encode` returns the encoded data plus a trailing - newline character (``b'\n'``). + an empty bytes object. :func:`encode` always appends trailing newline character + (``b'\n'``) to the encoded data. .. function:: encodebytes(s) encodestring(s) Encode the bytestring *s*, which can contain arbitrary binary data, and - return a bytestring containing one or more lines of base64-encoded data. + return a string containing one or more lines of base64-encoded data. :func:`encodebytes` returns a string containing one or more lines of base64-encoded data always including an extra trailing newline (``b'\n'``). ``encodestring`` is a deprecated alias. @@ -157,12 +157,12 @@ An example usage of the module: >>> import base64 - >>> encoded = base64.b64encode('data to be encoded') + >>> encoded = base64.b64encode(b'data to be encoded') >>> encoded - b'ZGF0YSB0byBiZSBlbmNvZGVk' + 'ZGF0YSB0byBiZSBlbmNvZGVk' >>> data = base64.b64decode(encoded) >>> data - 'data to be encoded' + b'data to be encoded' .. seealso:: Index: Doc/library/quopri.rst =================================================================== --- Doc/library/quopri.rst (revision 85127) +++ Doc/library/quopri.rst (working copy) @@ -28,7 +28,10 @@ described in :rfc:`1522`: "MIME (Multipurpose Internet Mail Extensions) Part Two: Message Header Extensions for Non-ASCII Text". + .. versionchanged:: 3.2 + Input must be a text file + .. function:: encode(input, output, quotetabs, header=False) Encode the contents of the *input* file and write the resulting quoted-printable @@ -40,20 +43,29 @@ end of lines are always encoded, as per :rfc:`1521`. *header* is a flag which controls if spaces are encoded as underscores as per :rfc:`1522`. + .. versionchanged:: 3.2 + Output must be a text file + .. function:: decodestring(s, header=False) Like :func:`decode`, except that it accepts a source string and returns the - corresponding decoded string. + corresponding decoded bytestring. + .. versionchanged:: 3.2 + *s* must be a Unicode string. + .. function:: encodestring(s, quotetabs=False, header=False) - Like :func:`encode`, except that it accepts a source string and returns the + Like :func:`encode`, except that it accepts a source bytestring and returns the corresponding encoded string. *quotetabs* and *header* are optional (defaulting to ``False``), and are passed straight through to :func:`encode`. + .. versionchanged:: 3.2 + Returns a unicode string. + .. seealso:: Module :mod:`base64` Index: Lib/xmlrpc/client.py =================================================================== --- Lib/xmlrpc/client.py (revision 85127) +++ Lib/xmlrpc/client.py (working copy) @@ -413,12 +413,12 @@ return self.data != other def decode(self, data): - self.data = base64.decodebytes(data) + self.data = base64.decodestring(data) def encode(self, out): out.write("\n") encoded = base64.encodebytes(self.data) - out.write(encoded.decode('ascii')) + out.write(encoded) out.write('\n') out.write("\n") @@ -768,7 +768,7 @@ def end_base64(self, data): value = Binary() - value.decode(data.encode("ascii")) + value.decode(data) self.append(value) self._value = 0 dispatch["base64"] = end_base64 @@ -1200,7 +1200,7 @@ if auth: import base64 auth = urllib.parse.unquote_to_bytes(auth) - auth = base64.encodebytes(auth).decode("utf-8") + auth = base64.encodebytes(auth) auth = "".join(auth.split()) # get rid of whitespace extra_headers = [ ("Authorization", "Basic " + auth) Index: Lib/json/decoder.py =================================================================== --- Lib/json/decoder.py (revision 85127) +++ Lib/json/decoder.py (working copy) @@ -16,7 +16,7 @@ FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL def _floatconstants(): - _BYTES = binascii.unhexlify(b'7FF80000000000007FF0000000000000') + _BYTES = binascii.unhexlify('7FF80000000000007FF0000000000000') if sys.byteorder != 'big': _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1] nan, inf = struct.unpack('dd', _BYTES) Index: Lib/smtplib.py =================================================================== --- Lib/smtplib.py (revision 85127) +++ Lib/smtplib.py (working copy) @@ -540,7 +540,7 @@ """ def encode_cram_md5(challenge, user, password): - challenge = base64.decodebytes(challenge) + challenge = base64.decodestring(challenge.decode('ascii')) response = user + " " + hmac.HMAC(password.encode('ascii'), challenge).hexdigest() return encode_base64(response.encode('ascii'), eol='') Index: Lib/quopri.py =================================================================== --- Lib/quopri.py (revision 85127) +++ Lib/quopri.py (working copy) @@ -6,10 +6,10 @@ __all__ = ["encode", "decode", "encodestring", "decodestring"] -ESCAPE = b'=' +ESCAPE = '=' MAXLINESIZE = 76 -HEX = b'0123456789ABCDEF' -EMPTYSTRING = b'' +HEX = '0123456789ABCDEF' +EMPTYSTRING = '' try: from binascii import a2b_qp, b2a_qp @@ -37,7 +37,7 @@ """Quote a single character.""" assert isinstance(c, bytes) and len(c)==1 c = ord(c) - return ESCAPE + bytes((HEX[c//16], HEX[c%16])) + return ESCAPE + HEX[c//16] + HEX[c%16] @@ -58,13 +58,13 @@ output.write(odata) return - def write(s, output=output, lineEnd=b'\n'): + def write(s, output=output, lineEnd='\n'): # RFC 1521 requires that the line ending in a space or tab must have # that trailing character encoded. - if s and s[-1:] in b' \t': - output.write(s[:-1] + quote(s[-1:]) + lineEnd) - elif s == b'.': - output.write(quote(s) + lineEnd) + if s and s[-1:] in ' \t': + output.write(s[:-1] + quote(s[-1:].encode("ascii")) + lineEnd) + elif s == '.': + output.write(quote(s.encode("ascii")) + lineEnd) else: output.write(s + lineEnd) @@ -75,18 +75,20 @@ break outline = [] # Strip off any readline induced trailing newline - stripped = b'' + stripped = '' if line[-1:] == b'\n': line = line[:-1] - stripped = b'\n' + stripped = '\n' # Calculate the un-length-limited encoded line for c in line: c = bytes((c,)) if needsquoting(c, quotetabs, header): c = quote(c) - if header and c == b' ': - outline.append(b'_') else: + c = c.decode("ascii") + if header and c == ' ': + outline.append('_') + else: outline.append(c) # First, write out the previous line if prevline is not None: @@ -97,7 +99,7 @@ while len(thisline) > MAXLINESIZE: # Don't forget to include the soft line break `=' sign in the # length calculation! - write(thisline[:MAXLINESIZE-1], lineEnd=b'=\n') + write(thisline[:MAXLINESIZE-1], lineEnd='=\n') thisline = thisline[MAXLINESIZE-1:] # Write out the current line prevline = thisline @@ -108,9 +110,9 @@ def encodestring(s, quotetabs=False, header=False): if b2a_qp is not None: return b2a_qp(s, quotetabs=quotetabs, header=header) - from io import BytesIO + from io import BytesIO, StringIO infp = BytesIO(s) - outfp = BytesIO() + outfp = StringIO() encode(infp, outfp, quotetabs, header) return outfp.getvalue() @@ -132,19 +134,19 @@ line = input.readline() if not line: break i, n = 0, len(line) - if n > 0 and line[n-1:n] == b'\n': + if n > 0 and line[n-1:n] == '\n': partial = 0; n = n-1 # Strip trailing whitespace - while n > 0 and line[n-1:n] in b" \t\r": + while n > 0 and line[n-1:n] in " \t\r": n = n-1 else: partial = 1 while i < n: c = line[i:i+1] - if c == b'_' and header: + if c == '_' and header: new = new + b' '; i = i+1 elif c != ESCAPE: - new = new + c; i = i+1 + new = new + c.encode("ascii"); i = i+1 elif i+1 == n and not partial: partial = 1; break elif i+1 < n and line[i+1] == ESCAPE: @@ -152,7 +154,7 @@ elif i+2 < n and ishex(line[i+1:i+2]) and ishex(line[i+2:i+3]): new = new + bytes((unhex(line[i+1:i+3]),)); i = i+3 else: # Bad escape sequence -- leave it in - new = new + c; i = i+1 + new = new + c.encode("ascii"); i = i+1 if not partial: output.write(new + b'\n') new = b'' @@ -162,8 +164,8 @@ def decodestring(s, header=False): if a2b_qp is not None: return a2b_qp(s, header=header) - from io import BytesIO - infp = BytesIO(s) + from io import BytesIO, StringIO + infp = StringIO(s) outfp = BytesIO() decode(infp, outfp, header=header) return outfp.getvalue() @@ -173,19 +175,18 @@ # Other helper functions def ishex(c): """Return true if the byte ordinal 'c' is a hexadecimal digit in ASCII.""" - assert isinstance(c, bytes) - return b'0' <= c <= b'9' or b'a' <= c <= b'f' or b'A' <= c <= b'F' + assert isinstance(c, str) + return '0' <= c <= '9' or 'a' <= c <= 'f' or 'A' <= c <= 'F' def unhex(s): """Get the integer value of a hexadecimal number.""" bits = 0 for c in s: - c = bytes((c,)) - if b'0' <= c <= b'9': + if '0' <= c <= '9': i = ord('0') - elif b'a' <= c <= b'f': + elif 'a' <= c <= 'f': i = ord('a')-10 - elif b'A' <= c <= b'F': + elif 'A' <= c <= 'F': i = ord(b'A')-10 else: assert False, "non-hex digit "+repr(c) @@ -219,10 +220,16 @@ sts = 0 for file in args: if file == '-': - fp = sys.stdin.buffer + if deco: + fp = sys.stdin + else: + fp = sys.stdin.buffer else: try: - fp = open(file, "rb") + if deco: + fp = open(file, "r") + else: + fp = open(file, "rb") except IOError as msg: sys.stderr.write("%s: can't open (%s)\n" % (file, msg)) sts = 1 @@ -231,7 +238,7 @@ if deco: decode(fp, sys.stdout.buffer) else: - encode(fp, sys.stdout.buffer, tabs) + encode(fp, sys.stdout, tabs) finally: if file != '-': fp.close() Index: Lib/http/server.py =================================================================== --- Lib/http/server.py (revision 85127) +++ Lib/http/server.py (working copy) @@ -1019,8 +1019,8 @@ env['AUTH_TYPE'] = authorization[0] if authorization[0].lower() == "basic": try: - authorization = authorization[1].encode('ascii') - authorization = base64.decodebytes(authorization).\ + authorization = authorization[1] + authorization = base64.decodestring(authorization).\ decode('ascii') except (binascii.Error, UnicodeError): pass Index: Lib/distutils/command/upload.py =================================================================== --- Lib/distutils/command/upload.py (revision 85127) +++ Lib/distutils/command/upload.py (working copy) @@ -127,7 +127,7 @@ user_pass = (self.username + ":" + self.password).encode('ascii') # The exact encoding of the authentication string is debated. # Anyway PyPI only accepts ascii for both username or password. - auth = "Basic " + standard_b64encode(user_pass).decode('ascii') + auth = "Basic " + standard_b64encode(user_pass) # Build up the MIME payload for the POST data boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' Index: Lib/urllib/request.py =================================================================== --- Lib/urllib/request.py (revision 85127) +++ Lib/urllib/request.py (working copy) @@ -667,7 +667,7 @@ if user and password: user_pass = '%s:%s' % (unquote(user), unquote(password)) - creds = base64.b64encode(user_pass.encode()).decode("ascii") + creds = base64.b64encode(user_pass.encode()) req.add_header('Proxy-authorization', 'Basic ' + creds) hostport = unquote(hostport) req.set_proxy(hostport, proxy_type) @@ -808,7 +808,7 @@ user, pw = self.passwd.find_user_password(realm, host) if pw is not None: raw = "%s:%s" % (user, pw) - auth = "Basic " + base64.b64encode(raw.encode()).decode("ascii") + auth = "Basic " + base64.b64encode(raw.encode()) if req.headers.get(self.auth_header, None) == auth: return None req.add_unredirected_header(self.auth_header, auth) @@ -1604,13 +1604,13 @@ if proxy_passwd: import base64 - proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('ascii') + proxy_auth = base64.b64encode(proxy_passwd.encode()) else: proxy_auth = None if user_passwd: import base64 - auth = base64.b64encode(user_passwd.encode()).decode('ascii') + auth = base64.b64encode(user_passwd.encode()) else: auth = None http_conn = connection_factory(host) @@ -1810,7 +1810,7 @@ if encoding == 'base64': import base64 # XXX is this encoding/decoding ok? - data = base64.decodebytes(data.encode('ascii')).decode('latin1') + data = base64.decodestring(data).decode('latin1') else: data = unquote(data) msg.append('Content-Length: %d' % len(data)) Index: Lib/base64.py =================================================================== --- Lib/base64.py (revision 85127) +++ Lib/base64.py (working copy) @@ -13,7 +13,7 @@ __all__ = [ # Legacy interface exports traditional RFC 1521 Base64 encodings - 'encode', 'decode', 'encodebytes', 'decodebytes', + 'encode', 'decode', 'encodebytes', 'decodestring', # Generalized interface for other encodings 'b64encode', 'b64decode', 'b32encode', 'b32decode', 'b16encode', 'b16decode', @@ -31,11 +31,11 @@ def _translate(s, altchars): - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) + if not isinstance(s, str): + raise TypeError("expected str, not %s" % s.__class__.__name__) translation = bytearray(range(256)) for k, v in altchars.items(): - translation[ord(k)] = v[0] + translation[ord(k)] = ord(v[0]) return s.translate(translation) @@ -57,8 +57,8 @@ # 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" + if not isinstance(altchars, str): + raise TypeError("expected str, not %s" % altchars.__class__.__name__) assert len(altchars) == 2, repr(altchars) return _translate(encoded, {'+': altchars[0:1], '/': altchars[1:2]}) @@ -66,9 +66,9 @@ def b64decode(s, altchars=None): - """Decode a Base64 encoded byte string. + """Decode a Base64 encoded string. - s is the byte string to decode. Optional altchars must be a + s is the string to decode. Optional altchars must be a string of length 2 which specifies the alternative alphabet used instead of the '+' and '/' characters. @@ -76,28 +76,28 @@ s were incorrectly padded or if there are non-alphabet characters present in the string. """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) + if not isinstance(s, str): + raise TypeError("expected str, not %s" % s.__class__.__name__) if altchars is not None: - if not isinstance(altchars, bytes_types): - raise TypeError("expected bytes, not %s" + if not isinstance(altchars, str): + raise TypeError("expected str, not %s" % altchars.__class__.__name__) assert len(altchars) == 2, repr(altchars) - s = _translate(s, {chr(altchars[0]): b'+', chr(altchars[1]): b'/'}) + s = _translate(s, {altchars[0]: '+', altchars[1]: '/'}) return binascii.a2b_base64(s) def standard_b64encode(s): """Encode a byte string using the standard Base64 alphabet. - s is the byte string to encode. The encoded byte string is returned. + s is the byte string to encode. The encoded string is returned. """ return b64encode(s) def standard_b64decode(s): - """Decode a byte string encoded with the standard Base64 alphabet. + """Decode a string encoded with the standard Base64 alphabet. - s is the byte string to decode. The decoded byte string is + s is the string to decode. The decoded byte string is returned. binascii.Error is raised if the input is incorrectly padded or if there are non-alphabet characters present in the input. @@ -107,37 +107,37 @@ def urlsafe_b64encode(s): """Encode a byte string using a url-safe Base64 alphabet. - s is the byte string to encode. The encoded byte string is + s is the byte string to encode. The encoded string is returned. The alphabet uses '-' instead of '+' and '_' instead of '/'. """ - return b64encode(s, b'-_') + return b64encode(s, '-_') def urlsafe_b64decode(s): - """Decode a byte string encoded with the standard Base64 alphabet. + """Decode a string encoded with the standard Base64 alphabet. - s is the byte string to decode. The decoded byte string is + s is the string to decode. The decoded byte string is returned. binascii.Error is raised if the input is incorrectly padded or if there are non-alphabet characters present in the input. The alphabet uses '-' instead of '+' and '_' instead of '/'. """ - return b64decode(s, b'-_') + return b64decode(s, '-_') # Base32 encoding/decoding must be done in Python _b32alphabet = { - 0: b'A', 9: b'J', 18: b'S', 27: b'3', - 1: b'B', 10: b'K', 19: b'T', 28: b'4', - 2: b'C', 11: b'L', 20: b'U', 29: b'5', - 3: b'D', 12: b'M', 21: b'V', 30: b'6', - 4: b'E', 13: b'N', 22: b'W', 31: b'7', - 5: b'F', 14: b'O', 23: b'X', - 6: b'G', 15: b'P', 24: b'Y', - 7: b'H', 16: b'Q', 25: b'Z', - 8: b'I', 17: b'R', 26: b'2', + 0: 'A', 9: 'J', 18: 'S', 27: '3', + 1: 'B', 10: 'K', 19: 'T', 28: '4', + 2: 'C', 11: 'L', 20: 'U', 29: '5', + 3: 'D', 12: 'M', 21: 'V', 30: '6', + 4: 'E', 13: 'N', 22: 'W', 31: '7', + 5: 'F', 14: 'O', 23: 'X', + 6: 'G', 15: 'P', 24: 'Y', + 7: 'H', 16: 'Q', 25: 'Z', + 8: 'I', 17: 'R', 26: '2', } _b32tab = [v[0] for k, v in sorted(_b32alphabet.items())] @@ -147,7 +147,7 @@ def b32encode(s): """Encode a byte string using Base32. - s is the byte string to encode. The encoded byte string is returned. + s is the byte string to encode. The encoded string is returned. """ if not isinstance(s, bytes_types): raise TypeError("expected bytes, not %s" % s.__class__.__name__) @@ -156,7 +156,7 @@ if leftover: s = s + bytes(5 - leftover) # Don't use += ! quanta += 1 - encoded = bytes() + encoded = str() for i in range(quanta): # c1 and c2 are 16 bits wide, c3 is 8 bits wide. The intent of this # code is to process the 40 bits in units of 5 bits. So we take the 1 @@ -166,31 +166,31 @@ c1, c2, c3 = struct.unpack('!HHB', s[i*5:(i+1)*5]) c2 += (c1 & 1) << 16 # 17 bits wide c3 += (c2 & 3) << 8 # 10 bits wide - encoded += bytes([_b32tab[c1 >> 11], # bits 1 - 5 - _b32tab[(c1 >> 6) & 0x1f], # bits 6 - 10 - _b32tab[(c1 >> 1) & 0x1f], # bits 11 - 15 - _b32tab[c2 >> 12], # bits 16 - 20 (1 - 5) - _b32tab[(c2 >> 7) & 0x1f], # bits 21 - 25 (6 - 10) - _b32tab[(c2 >> 2) & 0x1f], # bits 26 - 30 (11 - 15) - _b32tab[c3 >> 5], # bits 31 - 35 (1 - 5) - _b32tab[c3 & 0x1f], # bits 36 - 40 (1 - 5) - ]) + encoded += ''.join([_b32tab[c1 >> 11], # bits 1 - 5 + _b32tab[(c1 >> 6) & 0x1f], # bits 6 - 10 + _b32tab[(c1 >> 1) & 0x1f], # bits 11 - 15 + _b32tab[c2 >> 12], # bits 16 - 20 (1 - 5) + _b32tab[(c2 >> 7) & 0x1f], # bits 21 - 25 (6 - 10) + _b32tab[(c2 >> 2) & 0x1f], # bits 26 - 30 (11 - 15) + _b32tab[c3 >> 5], # bits 31 - 35 (1 - 5) + _b32tab[c3 & 0x1f], # bits 36 - 40 (1 - 5) + ]) # Adjust for any leftover partial quanta if leftover == 1: - return encoded[:-6] + b'======' + return encoded[:-6] + '======' elif leftover == 2: - return encoded[:-4] + b'====' + return encoded[:-4] + '====' elif leftover == 3: - return encoded[:-3] + b'===' + return encoded[:-3] + '===' elif leftover == 4: - return encoded[:-1] + b'=' + return encoded[:-1] + '=' return encoded def b32decode(s, casefold=False, map01=None): - """Decode a Base32 encoded byte string. + """Decode a Base32 encoded string. - s is the byte string to decode. Optional casefold is a flag + s is the string to decode. Optional casefold is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default is False. @@ -206,8 +206,8 @@ the input is incorrectly padded or if there are non-alphabet characters present in the input. """ - if not isinstance(s, bytes_types): - raise TypeError("expected bytes, not %s" % s.__class__.__name__) + if not isinstance(s, str): + raise TypeError("expected str, not %s" % s.__class__.__name__) quanta, leftover = divmod(len(s), 8) if leftover: raise binascii.Error('Incorrect padding') @@ -215,17 +215,17 @@ # False, or the character to map the digit 1 (one) to. It should be # either L (el) or I (eye). if map01 is not None: - if not isinstance(map01, bytes_types): - raise TypeError("expected bytes, not %s" % map01.__class__.__name__) + if not isinstance(map01, str): + raise TypeError("expected str, not %s" % map01.__class__.__name__) assert len(map01) == 1, repr(map01) - s = _translate(s, {b'0': b'O', b'1': map01}) + s = _translate(s, {'0': 'O', '1': map01}) if casefold: s = s.upper() # Strip off pad characters from the right. We need to count the pad # characters because this will tell us how many null bytes to remove from # the end of the decoded string. padchars = 0 - mo = re.search(b'(?P[=]*)$', s) + mo = re.search('(?P[=]*)$', s) if mo: padchars = len(mo.group('pad')) if padchars > 0: @@ -241,11 +241,11 @@ acc += _b32rev[c] << shift shift -= 5 if shift < 0: - parts.append(binascii.unhexlify(bytes('%010x' % acc, "ascii"))) + parts.append(binascii.unhexlify('%010x' % acc)) acc = 0 shift = 35 # Process the last, partial quanta - last = binascii.unhexlify(bytes('%010x' % acc, "ascii")) + last = binascii.unhexlify('%010x' % acc) if padchars == 0: last = b'' # No characters elif padchars == 1: @@ -269,7 +269,7 @@ def b16encode(s): """Encode a byte string using Base16. - s is the byte string to encode. The encoded byte string is returned. + s is the byte string to encode. The encoded string is returned. """ if not isinstance(s, bytes_types): raise TypeError("expected bytes, not %s" % s.__class__.__name__) @@ -277,9 +277,9 @@ def b16decode(s, casefold=False): - """Decode a Base16 encoded byte string. + """Decode a Base16 encoded string. - s is the byte string to decode. Optional casefold is a flag + s is the string to decode. Optional casefold is a flag specifying whether a lowercase alphabet is acceptable as input. For security purposes, the default is False. @@ -287,11 +287,11 @@ s were incorrectly padded or if there are non-alphabet characters present in the string. """ - if not isinstance(s, bytes_types): + if not isinstance(s, str): raise TypeError("expected bytes, not %s" % s.__class__.__name__) if casefold: s = s.upper() - if re.search(b'[^0-9A-F]', s): + if re.search('[^0-9A-F]', s): raise binascii.Error('Non-base16 digit found') return binascii.unhexlify(s) @@ -305,7 +305,7 @@ MAXBINSIZE = (MAXLINESIZE//4)*3 def encode(input, output): - """Encode a file; input and output are binary files.""" + """Encode a file; input is a binary file and output is a text file.""" while True: s = input.read(MAXBINSIZE) if not s: @@ -320,7 +320,7 @@ def decode(input, output): - """Decode a file; input and output are binary files.""" + """Decode a file; input is a text file and output is a binary file.""" while True: line = input.readline() if not line: @@ -330,7 +330,7 @@ def encodebytes(s): - """Encode a bytestring into a bytestring containing multiple lines + """Encode a bytestring into a string containing multiple lines of base-64 data.""" if not isinstance(s, bytes_types): raise TypeError("expected bytes, not %s" % s.__class__.__name__) @@ -338,7 +338,7 @@ for i in range(0, len(s), MAXBINSIZE): chunk = s[i : i + MAXBINSIZE] pieces.append(binascii.b2a_base64(chunk)) - return b"".join(pieces) + return "".join(pieces) def encodestring(s): """Legacy alias of encodebytes().""" @@ -347,20 +347,18 @@ DeprecationWarning, 2) return encodebytes(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__) - return binascii.a2b_base64(s) - -def decodestring(s): - """Legacy alias of decodebytes().""" + """Legacy alias of decodestring().""" import warnings - warnings.warn("decodestring() is a deprecated alias, use decodebytes()", + warnings.warn("decodebytes() is a deprecated alias, use decodestring()", DeprecationWarning, 2) - return decodebytes(s) + return decodestring(s) +def decodestring(s): + """Decode a string of base-64 data into a bytestring.""" + if not isinstance(s, str): + raise TypeError("expected str, not %s" % s.__class__.__name__) + return binascii.a2b_base64(s) # Usable as a script... def main(): @@ -382,10 +380,21 @@ if o == '-d': func = decode if o == '-u': func = decode if o == '-t': test(); return - if args and args[0] != '-': - func(open(args[0], 'rb'), sys.stdout.buffer) + # decode - input is text, output is binary + # encode - input is binary, output is text + if func == encode: + if args and args[0] != '-': + inpf = open(args[0], 'rb') + else: + inpf = sys.stdin.buffer + outpf = sys.stdout else: - func(sys.stdin.buffer, sys.stdout.buffer) + if args and args[0] != '-': + inpf = open(args[0], 'r') + else: + inpf = sys.stdin + outpf = sys.stdout.buffer + func(inpf, outpf) def test(): @@ -393,7 +402,7 @@ print(repr(s0)) s1 = encodebytes(s0) print(repr(s1)) - s2 = decodebytes(s1) + s2 = decodestring(s1) print(repr(s2)) assert s0 == s2 Index: Lib/ctypes/test/test_byteswap.py =================================================================== --- Lib/ctypes/test/test_byteswap.py (revision 85127) +++ Lib/ctypes/test/test_byteswap.py (working copy) @@ -4,7 +4,7 @@ from ctypes import * def bin(s): - return hexlify(memoryview(s)).decode().upper() + return hexlify(memoryview(s)).upper() # Each *simple* type that supports different byte orders has an # __ctype_be__ attribute that specifies the same type in BIG ENDIAN Index: Lib/ctypes/test/test_array_in_pointer.py =================================================================== --- Lib/ctypes/test/test_array_in_pointer.py (revision 85127) +++ Lib/ctypes/test/test_array_in_pointer.py (working copy) @@ -6,7 +6,7 @@ def dump(obj): # helper function to dump memory contents in hex, with a hyphen # between the bytes. - h = hexlify(memoryview(obj)).decode() + h = hexlify(memoryview(obj)) return re.sub(r"(..)", r"\1-", h)[:-1] Index: Lib/email/test/test_email.py =================================================================== --- Lib/email/test/test_email.py (revision 85127) +++ Lib/email/test/test_email.py (working copy) @@ -970,7 +970,7 @@ def test_encoding(self): payload = self._au.get_payload() - self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self.assertEqual(base64.decodestring(payload), self._audiodata) def test_checkSetMinor(self): @@ -1011,7 +1011,7 @@ def test_encoding(self): payload = self._im.get_payload() - self.assertEqual(base64.decodebytes(bytes(payload, 'ascii')), + self.assertEqual(base64.decodestring(payload), self._imgdata) def test_checkSetMinor(self): Index: Lib/email/base64mime.py =================================================================== --- Lib/email/base64mime.py (revision 85127) +++ Lib/email/base64mime.py (working copy) @@ -68,7 +68,7 @@ return "" if isinstance(header_bytes, str): header_bytes = header_bytes.encode(charset) - encoded = b64encode(header_bytes).decode("ascii") + encoded = b64encode(header_bytes) return '=?%s?b?%s?=' % (charset, encoded) @@ -91,7 +91,7 @@ for i in range(0, len(s), max_unencoded): # BAW: should encode() inherit b2a_base64()'s dubious behavior in # adding a newline to the encoded string? - enc = b2a_base64(s[i:i + max_unencoded]).decode("ascii") + enc = b2a_base64(s[i:i + max_unencoded]) if enc.endswith(NL) and eol != NL: enc = enc[:-1] + eol encvec.append(enc) @@ -108,10 +108,7 @@ """ if not string: return bytes() - elif isinstance(string, str): - return a2b_base64(string.encode('raw-unicode-escape')) - else: - return a2b_base64(string) + return a2b_base64(string) # For convenience and backwards compatibility w/ standard base64 module Index: Lib/email/encoders.py =================================================================== --- Lib/email/encoders.py (revision 85127) +++ Lib/email/encoders.py (working copy) @@ -29,7 +29,7 @@ Also, add an appropriate Content-Transfer-Encoding header. """ orig = msg.get_payload() - encdata = str(_bencode(orig), 'ascii') + encdata = _bencode(orig) msg.set_payload(encdata) msg['Content-Transfer-Encoding'] = 'base64' Index: Lib/email/message.py =================================================================== --- Lib/email/message.py (revision 85127) +++ Lib/email/message.py (working copy) @@ -198,19 +198,15 @@ return None cte = self.get('content-transfer-encoding', '').lower() if cte == 'quoted-printable': - if isinstance(payload, str): - payload = payload.encode('ascii') return utils._qdecode(payload) elif cte == 'base64': try: - if isinstance(payload, str): - payload = payload.encode('ascii') return base64.b64decode(payload) except binascii.Error: # Incorrect padding pass elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'): - in_file = BytesIO(payload.encode('ascii')) + in_file = StringIO(payload) out_file = BytesIO() try: uu.decode(in_file, out_file, quiet=True) Index: Lib/ssl.py =================================================================== --- Lib/ssl.py (revision 85127) +++ Lib/ssl.py (working copy) @@ -448,7 +448,7 @@ raise ValueError("Invalid PEM encoding; must end with %s" % PEM_FOOTER) d = pem_cert_string.strip()[len(PEM_HEADER):-len(PEM_FOOTER)] - return base64.decodebytes(d.encode('ASCII', 'strict')) + return base64.decodestring(d.encode('ASCII', 'strict')) def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): """Retrieve the certificate from the server at the specified address, Index: Lib/plistlib.py =================================================================== --- Lib/plistlib.py (revision 85127) +++ Lib/plistlib.py (working copy) @@ -226,7 +226,7 @@ self.indentLevel -= 1 maxlinelength = 76 - len(self.indent.replace(b"\t", b" " * 8) * self.indentLevel) - for line in data.asBase64(maxlinelength).split(b"\n"): + for line in data.asBase64(maxlinelength).split("\n"): if line: self.writeln(line) self.indentLevel += 1 @@ -321,7 +321,7 @@ for i in range(0, len(s), maxbinsize): chunk = s[i : i + maxbinsize] pieces.append(binascii.b2a_base64(chunk)) - return b''.join(pieces) + return ''.join(pieces) class Data: @@ -428,6 +428,6 @@ def end_string(self): self.addObject(self.getData()) def end_data(self): - self.addObject(Data.fromBase64(self.getData().encode("utf-8"))) + self.addObject(Data.fromBase64(self.getData())) def end_date(self): self.addObject(_dateFromString(self.getData())) Index: Lib/test/test_descr.py =================================================================== --- Lib/test/test_descr.py (revision 85127) +++ Lib/test/test_descr.py (working copy) @@ -3252,7 +3252,7 @@ class octetstring(str): def __str__(self): - return binascii.b2a_hex(self.encode('ascii')).decode("ascii") + return binascii.b2a_hex(self.encode('ascii')) def __repr__(self): return self + " repr" Index: Lib/test/test_quopri.py =================================================================== --- Lib/test/test_quopri.py (revision 85127) +++ Lib/test/test_quopri.py (working copy) @@ -6,7 +6,7 @@ -ENCSAMPLE = b"""\ +ENCSAMPLE = """\ Here's a bunch of special=20 =A1=A2=A3=A4=A5=A6=A7=A8=A9 @@ -67,40 +67,40 @@ # used in the "quotetabs=0" tests. STRINGS = ( # Some normal strings - (b'hello', b'hello'), + (b'hello', 'hello'), (b'''hello there - world''', b'''hello + world''', '''hello there world'''), (b'''hello there world -''', b'''hello +''', '''hello there world '''), - (b'\201\202\203', b'=81=82=83'), + (b'\201\202\203', '=81=82=83'), # Add some trailing MUST QUOTE strings - (b'hello ', b'hello=20'), - (b'hello\t', b'hello=09'), + (b'hello ', 'hello=20'), + (b'hello\t', 'hello=09'), # Some long lines. First, a single line of 108 characters (b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\xd8\xd9\xda\xdb\xdc\xdd\xde\xdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - b'''xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=D8=D9=DA=DB=DC=DD=DE=DFx= + '''xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=D8=D9=DA=DB=DC=DD=DE=DFx= xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'''), # A line of exactly 76 characters, no soft line break should be needed (b'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', - b'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'), + 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'), # A line of 77 characters, forcing a soft line break at position 75, # and a second line of exactly 2 characters (because the soft line # break `=' sign counts against the line length limit). (b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz', - b'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz= + '''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz= zz'''), # A line of 151 characters, forcing a soft line break at position 75, # with a second line of exactly 76 characters and no trailing = (b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz', - b'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz= + '''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz= zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''), # A string containing a hard line break, but which the first line is # 151 characters and the second line is exactly 76 characters. This @@ -108,7 +108,7 @@ # break, and which the second and third do not. (b'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''', - b'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy= + '''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy= yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''), # Now some really complex stuff ;) @@ -117,14 +117,14 @@ # These are used in the "quotetabs=1" tests. ESTRINGS = ( - (b'hello world', b'hello=20world'), - (b'hello\tworld', b'hello=09world'), + (b'hello world', 'hello=20world'), + (b'hello\tworld', 'hello=09world'), ) # These are used in the "header=1" tests. HSTRINGS = ( - (b'hello world', b'hello_world'), - (b'hello_world', b'hello=5Fworld'), + (b'hello world', 'hello_world'), + (b'hello_world', 'hello=5Fworld'), ) @withpythonimplementation @@ -140,20 +140,21 @@ @withpythonimplementation def test_idempotent_string(self): for p, e in self.STRINGS: - self.assertEqual(quopri.decodestring(quopri.encodestring(e)), e) + self.assertEqual(quopri.decodestring(quopri.encodestring(p)), p) + self.assertEqual(quopri.encodestring(quopri.decodestring(e)), e) @withpythonimplementation def test_encode(self): for p, e in self.STRINGS: infp = io.BytesIO(p) - outfp = io.BytesIO() + outfp = io.StringIO() quopri.encode(infp, outfp, quotetabs=False) self.assertEqual(outfp.getvalue(), e) @withpythonimplementation def test_decode(self): for p, e in self.STRINGS: - infp = io.BytesIO(e) + infp = io.StringIO(e) outfp = io.BytesIO() quopri.decode(infp, outfp) self.assertEqual(outfp.getvalue(), p) @@ -183,7 +184,7 @@ # CRLF, as the mode of stdout is text mode. To compare this # with the expected result, we need to do a line-by-line comparison. cout = cout.decode('latin-1').splitlines() - e = e.decode('latin-1').splitlines() + e = e.splitlines() assert len(cout)==len(e) for i in range(len(cout)): self.assertEqual(cout[i], e[i]) @@ -193,7 +194,7 @@ (p, e) = self.STRINGS[-1] process = subprocess.Popen([sys.executable, "-mquopri", "-d"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) - cout, cerr = process.communicate(e) + cout, cerr = process.communicate(e.encode('latin-1')) cout = cout.decode('latin-1') p = p.decode('latin-1') self.assertEqual(cout.splitlines(), p.splitlines()) Index: Lib/test/test_uu.py =================================================================== --- Lib/test/test_uu.py (revision 85127) +++ Lib/test/test_uu.py (working copy) @@ -13,7 +13,7 @@ plaintext = b"The smooth-scaled python crept over the sleeping dog\n" -encodedtext = b"""\ +encodedtext = """\ M5&AE('-M;V]T:\"US8V%L960@<'ET:&]N(&-R97!T(&]V97(@=&AE('-L965P (:6YG(&1O9PH """ @@ -46,29 +46,29 @@ def encodedtextwrapped(mode, filename): - return (bytes("begin %03o %s\n" % (mode, filename), "ascii") + - encodedtext + b"\n \nend\n") + return ("begin %03o %s\n" % (mode, filename) + + encodedtext + "\n \nend\n") class UUTest(unittest.TestCase): def test_encode(self): inp = io.BytesIO(plaintext) - out = io.BytesIO() + out = io.StringIO() uu.encode(inp, out, "t1") self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1")) inp = io.BytesIO(plaintext) - out = io.BytesIO() + out = io.StringIO() uu.encode(inp, out, "t1", 0o644) self.assertEqual(out.getvalue(), encodedtextwrapped(0o644, "t1")) def test_decode(self): - inp = io.BytesIO(encodedtextwrapped(0o666, "t1")) + inp = io.StringIO(encodedtextwrapped(0o666, "t1")) out = io.BytesIO() uu.decode(inp, out) self.assertEqual(out.getvalue(), plaintext) - inp = io.BytesIO( - b"UUencoded files may contain many lines,\n" + - b"even some that have 'begin' in them.\n" + + inp = io.StringIO( + "UUencoded files may contain many lines,\n" + + "even some that have 'begin' in them.\n" + encodedtextwrapped(0o666, "t1") ) out = io.BytesIO() @@ -76,7 +76,7 @@ self.assertEqual(out.getvalue(), plaintext) def test_truncatedinput(self): - inp = io.BytesIO(b"begin 644 t1\n" + encodedtext) + inp = io.StringIO("begin 644 t1\n" + encodedtext) out = io.BytesIO() try: uu.decode(inp, out) @@ -85,7 +85,7 @@ self.assertEqual(str(e), "Truncated input file") def test_missingbegin(self): - inp = io.BytesIO(b"") + inp = io.StringIO("") out = io.BytesIO() try: uu.decode(inp, out) @@ -108,10 +108,10 @@ sys.stdout = FakeIO() uu.encode("-", "-", "t1", 0o666) self.assertEqual(sys.stdout.getvalue(), - encodedtextwrapped(0o666, "t1").decode("ascii")) + encodedtextwrapped(0o666, "t1")) def test_decode(self): - sys.stdin = FakeIO(encodedtextwrapped(0o666, "t1").decode("ascii")) + sys.stdin = FakeIO(encodedtextwrapped(0o666, "t1")) sys.stdout = FakeIO() uu.decode("-", "-") stdout = sys.stdout @@ -155,19 +155,19 @@ fin.close() fin = open(self.tmpin, 'rb') - fout = open(self.tmpout, 'wb') + fout = open(self.tmpout, 'w') uu.encode(fin, fout, self.tmpin, mode=0o644) fin.close() fout.close() - fout = open(self.tmpout, 'rb') + fout = open(self.tmpout, 'r') s = fout.read() fout.close() self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin)) # in_file and out_file as filenames uu.encode(self.tmpin, self.tmpout, self.tmpin, mode=0o644) - fout = open(self.tmpout, 'rb') + fout = open(self.tmpout, 'r') s = fout.read() fout.close() self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin)) @@ -180,11 +180,11 @@ f = None try: support.unlink(self.tmpin) - f = open(self.tmpin, 'wb') + f = open(self.tmpin, 'w') f.write(encodedtextwrapped(0o644, self.tmpout)) f.close() - f = open(self.tmpin, 'rb') + f = open(self.tmpin, 'r') uu.decode(f) f.close() @@ -200,13 +200,13 @@ # Verify that decode() will refuse to overwrite an existing file f = None try: - f = io.BytesIO(encodedtextwrapped(0o644, self.tmpout)) + f = io.StringIO(encodedtextwrapped(0o644, self.tmpout)) - f = open(self.tmpin, 'rb') + f = open(self.tmpin, 'r') uu.decode(f) f.close() - f = open(self.tmpin, 'rb') + f = open(self.tmpin, 'r') self.assertRaises(uu.Error, uu.decode, f) f.close() finally: Index: Lib/test/test_binascii.py =================================================================== --- Lib/test/test_binascii.py (revision 85127) +++ Lib/test/test_binascii.py (working copy) @@ -7,10 +7,11 @@ # Note: "*_hex" functions are aliases for "(un)hexlify" b2a_functions = ['b2a_base64', 'b2a_hex', 'b2a_hqx', 'b2a_qp', 'b2a_uu', - 'hexlify', 'rlecode_hqx'] + 'hexlify'] a2b_functions = ['a2b_base64', 'a2b_hex', 'a2b_hqx', 'a2b_qp', 'a2b_uu', - 'unhexlify', 'rledecode_hqx'] -all_functions = a2b_functions + b2a_functions + ['crc32', 'crc_hqx'] + 'unhexlify'] +b2b_functions = ['rlecode_hqx', 'rledecode_hqx'] +all_functions = a2b_functions + b2a_functions + b2b_functions + ['crc32', 'crc_hqx'] class BinASCIITest(unittest.TestCase): @@ -45,7 +46,7 @@ b2a = getattr(binascii, fb) try: a = b2a(self.type2test(raw)) - res = a2b(self.type2test(a)) + res = a2b(a) except Exception as err: self.fail("{}/{} conversion raises {!r}".format(fb, fa, err)) if fb == 'b2a_hqx': @@ -54,10 +55,15 @@ self.assertEqual(res, raw, "{}/{} conversion: " "{!r} != {!r}".format(fb, fa, res, raw)) self.assertIsInstance(res, bytes) - self.assertIsInstance(a, bytes) - self.assertLess(max(a), 128) + self.assertIsInstance(a, str) self.assertIsInstance(binascii.crc_hqx(raw, 0), int) self.assertIsInstance(binascii.crc32(raw), int) + # and now the b2b functions + encoded = binascii.rlecode_hqx(raw) + decoded = binascii.rledecode_hqx(encoded) + self.assertEqual(raw, decoded) + self.assertIsInstance(encoded, bytes) + self.assertIsInstance(decoded, bytes) def test_base64valid(self): # Test base64 with valid data @@ -69,7 +75,7 @@ lines.append(a) res = bytes() for line in lines: - a = self.type2test(line) + a = line b = binascii.a2b_base64(a) res += b self.assertEqual(res, self.rawdata) @@ -84,32 +90,32 @@ a = binascii.b2a_base64(b) lines.append(a) - fillers = bytearray() - valid = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" + fillers = "" + valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" for i in range(256): - if i not in valid: - fillers.append(i) + if chr(i) not in valid: + fillers += chr(i) def addnoise(line): noise = fillers ratio = len(line) // len(noise) - res = bytearray() + res = "" while line and noise: if len(line) // len(noise) > ratio: c, line = line[0], line[1:] else: c, noise = noise[0], noise[1:] - res.append(c) + res += c return res + noise + line - res = bytearray() + res = b"" for line in map(addnoise, lines): - a = self.type2test(line) + a = line b = binascii.a2b_base64(a) res += b self.assertEqual(res, self.rawdata) # Test base64 with just invalid characters, which should return # empty strings. TBD: shouldn't it raise an exception instead ? - self.assertEqual(binascii.a2b_base64(self.type2test(fillers)), b'') + self.assertEqual(binascii.a2b_base64(fillers), b'') def test_uu(self): MAX_UU = 45 @@ -120,21 +126,21 @@ lines.append(a) res = bytes() for line in lines: - a = self.type2test(line) + a = line b = binascii.a2b_uu(a) res += b self.assertEqual(res, self.rawdata) - self.assertEqual(binascii.a2b_uu(b"\x7f"), b"\x00"*31) - self.assertEqual(binascii.a2b_uu(b"\x80"), b"\x00"*32) - self.assertEqual(binascii.a2b_uu(b"\xff"), b"\x00"*31) - self.assertRaises(binascii.Error, binascii.a2b_uu, b"\xff\x00") - self.assertRaises(binascii.Error, binascii.a2b_uu, b"!!!!") + self.assertEqual(binascii.a2b_uu("\x7f"), b"\x00"*31) + self.assertEqual(binascii.a2b_uu("\x80"), b"\x00"*32) + self.assertEqual(binascii.a2b_uu("\xff"), b"\x00"*31) + self.assertRaises(binascii.Error, binascii.a2b_uu, "\xff\x00") + self.assertRaises(binascii.Error, binascii.a2b_uu, "!!!!") self.assertRaises(binascii.Error, binascii.b2a_uu, 46*b"!") # Issue #7701 (crash on a pydebug build) - self.assertEqual(binascii.b2a_uu(b'x'), b'!> \n') + self.assertEqual(binascii.b2a_uu(b'x'), '!> \n') def test_crc32(self): crc = binascii.crc32(self.type2test(b"Test the CRC-32 of")) @@ -148,7 +154,7 @@ # Then calculate the hexbin4 binary-to-ASCII translation rle = binascii.rlecode_hqx(self.data) a = binascii.b2a_hqx(self.type2test(rle)) - b, _ = binascii.a2b_hqx(self.type2test(a)) + b, _ = binascii.a2b_hqx(a) res = binascii.rledecode_hqx(b) self.assertEqual(res, self.rawdata) @@ -157,47 +163,50 @@ # test hexlification s = b'{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000' t = binascii.b2a_hex(self.type2test(s)) - u = binascii.a2b_hex(self.type2test(t)) + u = binascii.a2b_hex(t) self.assertEqual(s, u) - self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1]) - self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1] + b'q') + self.assertRaises(ValueError, binascii.a2b_hex, t[:-1]) + self.assertRaises(ValueError, binascii.a2b_hex, t[:-1] + 'q') - self.assertEqual(binascii.hexlify(b'a'), b'61') + self.assertEqual(binascii.hexlify(b'a'), '61') def test_qp(self): # A test for SF bug 534347 (segfaults without the proper fix) try: - binascii.a2b_qp(b"", **{1:1}) + binascii.a2b_qp("", **{1:1}) except TypeError: pass else: self.fail("binascii.a2b_qp(**{1:1}) didn't raise TypeError") - self.assertEqual(binascii.a2b_qp(b"= "), b"= ") - self.assertEqual(binascii.a2b_qp(b"=="), b"=") - self.assertEqual(binascii.a2b_qp(b"=AX"), b"=AX") + self.assertEqual(binascii.a2b_qp("= "), b"= ") + self.assertEqual(binascii.a2b_qp("=="), b"=") + self.assertEqual(binascii.a2b_qp("=AX"), b"=AX") self.assertRaises(TypeError, binascii.b2a_qp, foo="bar") - self.assertEqual(binascii.a2b_qp(b"=00\r\n=00"), b"\x00\r\n\x00") + self.assertEqual(binascii.a2b_qp("=00\r\n=00"), b"\x00\r\n\x00") self.assertEqual( binascii.b2a_qp(b"\xff\r\n\xff\n\xff"), - b"=FF\r\n=FF\r\n=FF") + "=FF\r\n=FF\r\n=FF") self.assertEqual( binascii.b2a_qp(b"0"*75+b"\xff\r\n\xff\r\n\xff"), - b"0"*75+b"=\r\n=FF\r\n=FF\r\n=FF") + "0"*75+"=\r\n=FF\r\n=FF\r\n=FF") - self.assertEqual(binascii.b2a_qp(b'\0\n'), b'=00\n') - self.assertEqual(binascii.b2a_qp(b'\0\n', quotetabs=True), b'=00\n') - self.assertEqual(binascii.b2a_qp(b'foo\tbar\t\n'), b'foo\tbar=09\n') + self.assertEqual(binascii.b2a_qp(b'\0\n'), '=00\n') + self.assertEqual(binascii.b2a_qp(b'\0\n', quotetabs=True), '=00\n') + self.assertEqual(binascii.b2a_qp(b'foo\tbar\t\n'), 'foo\tbar=09\n') self.assertEqual(binascii.b2a_qp(b'foo\tbar\t\n', quotetabs=True), - b'foo=09bar=09\n') + 'foo=09bar=09\n') - self.assertEqual(binascii.b2a_qp(b'.'), b'=2E') - self.assertEqual(binascii.b2a_qp(b'.\n'), b'=2E\n') - self.assertEqual(binascii.b2a_qp(b'a.\n'), b'a.\n') + self.assertEqual(binascii.b2a_qp(b'.'), '=2E') + self.assertEqual(binascii.b2a_qp(b'.\n'), '=2E\n') + self.assertEqual(binascii.b2a_qp(b'a.\n'), 'a.\n') def test_empty_string(self): # A test for SF bug #1022953. Make sure SystemError is not raised. - empty = self.type2test(b'') for func in all_functions: + if func in a2b_functions: + empty = '' + else: + empty = self.type2test(b'') if func == 'crc_hqx': # crc_hqx needs 2 arguments binascii.crc_hqx(empty, 0) @@ -210,11 +219,16 @@ def test_unicode_strings(self): # Unicode strings are not accepted. - for func in all_functions: + for func in b2a_functions: try: self.assertRaises(TypeError, getattr(binascii, func), "test") except Exception as err: self.fail('{}("test") raises {!r}'.format(func, err)) + for func in a2b_functions: + try: + self.assertRaises(TypeError, getattr(binascii, func), b"test") + except Exception as err: + self.fail('{}("test") raises {!r}'.format(func, err)) # crc_hqx needs 2 arguments self.assertRaises(TypeError, binascii.crc_hqx, "test", 0) Index: Lib/test/test_httpservers.py =================================================================== --- Lib/test/test_httpservers.py (revision 85127) +++ Lib/test/test_httpservers.py (working copy) @@ -390,7 +390,7 @@ self.assertEqual(res.status, 404) def test_authorization(self): - headers = {b'Authorization' : b'Basic ' + + headers = {'Authorization' : 'Basic ' + base64.b64encode(b'username:pass')} res = self.request('/cgi-bin/file1.py', 'GET', headers=headers) self.assertEqual((b'Hello World\n', 'text/html', 200), Index: Lib/test/test_base64.py =================================================================== --- Lib/test/test_base64.py (revision 85127) +++ Lib/test/test_base64.py (working copy) @@ -10,50 +10,50 @@ class LegacyBase64TestCase(unittest.TestCase): def test_encodebytes(self): eq = self.assertEqual - eq(base64.encodebytes(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=\n") - eq(base64.encodebytes(b"a"), b"YQ==\n") - eq(base64.encodebytes(b"ab"), b"YWI=\n") - eq(base64.encodebytes(b"abc"), b"YWJj\n") - eq(base64.encodebytes(b""), b"") + eq(base64.encodebytes(b"www.python.org"), "d3d3LnB5dGhvbi5vcmc=\n") + eq(base64.encodebytes(b"a"), "YQ==\n") + eq(base64.encodebytes(b"ab"), "YWI=\n") + eq(base64.encodebytes(b"abc"), "YWJj\n") + eq(base64.encodebytes(b""), "") eq(base64.encodebytes(b"abcdefghijklmnopqrstuvwxyz" b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"0123456789!@#0^&*();:<>,. []{}"), - b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n") + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" + "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" + "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n") self.assertRaises(TypeError, base64.encodebytes, "") - def test_decodebytes(self): + def test_decodestring(self): eq = self.assertEqual - eq(base64.decodebytes(b"d3d3LnB5dGhvbi5vcmc=\n"), b"www.python.org") - eq(base64.decodebytes(b"YQ==\n"), b"a") - eq(base64.decodebytes(b"YWI=\n"), b"ab") - eq(base64.decodebytes(b"YWJj\n"), b"abc") - eq(base64.decodebytes(b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n"), + eq(base64.decodestring("d3d3LnB5dGhvbi5vcmc=\n"), b"www.python.org") + eq(base64.decodestring("YQ==\n"), b"a") + eq(base64.decodestring("YWI=\n"), b"ab") + eq(base64.decodestring("YWJj\n"), b"abc") + eq(base64.decodestring("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" + "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" + "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n"), b"abcdefghijklmnopqrstuvwxyz" b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"0123456789!@#0^&*();:<>,. []{}") - eq(base64.decodebytes(b''), b'') - self.assertRaises(TypeError, base64.decodebytes, "") + eq(base64.decodestring(''), b'') + self.assertRaises(TypeError, base64.decodestring, b"") def test_encode(self): eq = self.assertEqual - from io import BytesIO + from io import BytesIO, StringIO infp = BytesIO(b'abcdefghijklmnopqrstuvwxyz' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' b'0123456789!@#0^&*();:<>,. []{}') - outfp = BytesIO() + outfp = StringIO() base64.encode(infp, outfp) eq(outfp.getvalue(), - b'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE' - b'RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT' - b'Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n') + 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE' + 'RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT' + 'Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==\n') def test_decode(self): - from io import BytesIO - infp = BytesIO(b'd3d3LnB5dGhvbi5vcmc=') + from io import BytesIO, StringIO + infp = StringIO('d3d3LnB5dGhvbi5vcmc=') outfp = BytesIO() base64.decode(infp, outfp) self.assertEqual(outfp.getvalue(), b'www.python.org') @@ -63,147 +63,147 @@ def test_b64encode(self): eq = self.assertEqual # Test default alphabet - eq(base64.b64encode(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=") - eq(base64.b64encode(b'\x00'), b'AA==') - eq(base64.b64encode(b"a"), b"YQ==") - eq(base64.b64encode(b"ab"), b"YWI=") - eq(base64.b64encode(b"abc"), b"YWJj") - eq(base64.b64encode(b""), b"") + eq(base64.b64encode(b"www.python.org"), "d3d3LnB5dGhvbi5vcmc=") + eq(base64.b64encode(b'\x00'), 'AA==') + eq(base64.b64encode(b"a"), "YQ==") + eq(base64.b64encode(b"ab"), "YWI=") + eq(base64.b64encode(b"abc"), "YWJj") + eq(base64.b64encode(b""), "") eq(base64.b64encode(b"abcdefghijklmnopqrstuvwxyz" b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"0123456789!@#0^&*();:<>,. []{}"), - b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==") + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" + "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" + "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==") # Test with arbitrary alternative characters - eq(base64.b64encode(b'\xd3V\xbeo\xf7\x1d', altchars=b'*$'), b'01a*b$cd') + eq(base64.b64encode(b'\xd3V\xbeo\xf7\x1d', altchars='*$'), '01a*b$cd') # Check if passing a str object raises an error self.assertRaises(TypeError, base64.b64encode, "") - self.assertRaises(TypeError, base64.b64encode, b"", altchars="") + self.assertRaises(TypeError, base64.b64encode, b"", altchars=b"") # Test standard alphabet - eq(base64.standard_b64encode(b"www.python.org"), b"d3d3LnB5dGhvbi5vcmc=") - eq(base64.standard_b64encode(b"a"), b"YQ==") - eq(base64.standard_b64encode(b"ab"), b"YWI=") - eq(base64.standard_b64encode(b"abc"), b"YWJj") - eq(base64.standard_b64encode(b""), b"") + eq(base64.standard_b64encode(b"www.python.org"), "d3d3LnB5dGhvbi5vcmc=") + eq(base64.standard_b64encode(b"a"), "YQ==") + eq(base64.standard_b64encode(b"ab"), "YWI=") + eq(base64.standard_b64encode(b"abc"), "YWJj") + eq(base64.standard_b64encode(b""), "") eq(base64.standard_b64encode(b"abcdefghijklmnopqrstuvwxyz" b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"0123456789!@#0^&*();:<>,. []{}"), - b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==") + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" + "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" + "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==") # Check if passing a str object raises an error self.assertRaises(TypeError, base64.standard_b64encode, "") - self.assertRaises(TypeError, base64.standard_b64encode, b"", altchars="") + self.assertRaises(TypeError, base64.standard_b64encode, b"", altchars=b"") # Test with 'URL safe' alternative characters - eq(base64.urlsafe_b64encode(b'\xd3V\xbeo\xf7\x1d'), b'01a-b_cd') + eq(base64.urlsafe_b64encode(b'\xd3V\xbeo\xf7\x1d'), '01a-b_cd') # Check if passing a str object raises an error self.assertRaises(TypeError, base64.urlsafe_b64encode, "") def test_b64decode(self): eq = self.assertEqual - eq(base64.b64decode(b"d3d3LnB5dGhvbi5vcmc="), b"www.python.org") - eq(base64.b64decode(b'AA=='), b'\x00') - eq(base64.b64decode(b"YQ=="), b"a") - eq(base64.b64decode(b"YWI="), b"ab") - eq(base64.b64decode(b"YWJj"), b"abc") - eq(base64.b64decode(b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="), + eq(base64.b64decode("d3d3LnB5dGhvbi5vcmc="), b"www.python.org") + eq(base64.b64decode('AA=='), b'\x00') + eq(base64.b64decode("YQ=="), b"a") + eq(base64.b64decode("YWI="), b"ab") + eq(base64.b64decode("YWJj"), b"abc") + eq(base64.b64decode("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" + "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\nNT" + "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="), b"abcdefghijklmnopqrstuvwxyz" b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"0123456789!@#0^&*();:<>,. []{}") - eq(base64.b64decode(b''), b'') + eq(base64.b64decode(''), b'') # Test with arbitrary alternative characters - eq(base64.b64decode(b'01a*b$cd', altchars=b'*$'), b'\xd3V\xbeo\xf7\x1d') + eq(base64.b64decode('01a*b$cd', altchars='*$'), b'\xd3V\xbeo\xf7\x1d') # Check if passing a str object raises an error - self.assertRaises(TypeError, base64.b64decode, "") - self.assertRaises(TypeError, base64.b64decode, b"", altchars="") + self.assertRaises(TypeError, base64.b64decode, b"") + self.assertRaises(TypeError, base64.b64decode, "", altchars=b"") # Test standard alphabet - eq(base64.standard_b64decode(b"d3d3LnB5dGhvbi5vcmc="), b"www.python.org") - eq(base64.standard_b64decode(b"YQ=="), b"a") - eq(base64.standard_b64decode(b"YWI="), b"ab") - eq(base64.standard_b64decode(b"YWJj"), b"abc") - eq(base64.standard_b64decode(b""), b"") - eq(base64.standard_b64decode(b"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" - b"RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" - b"Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="), + eq(base64.standard_b64decode("d3d3LnB5dGhvbi5vcmc="), b"www.python.org") + eq(base64.standard_b64decode("YQ=="), b"a") + eq(base64.standard_b64decode("YWI="), b"ab") + eq(base64.standard_b64decode("YWJj"), b"abc") + eq(base64.standard_b64decode(""), b"") + eq(base64.standard_b64decode("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNE" + "RUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NT" + "Y3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ=="), b"abcdefghijklmnopqrstuvwxyz" b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"0123456789!@#0^&*();:<>,. []{}") # Check if passing a str object raises an error - self.assertRaises(TypeError, base64.standard_b64decode, "") - self.assertRaises(TypeError, base64.standard_b64decode, b"", altchars="") + self.assertRaises(TypeError, base64.standard_b64decode, b"") + self.assertRaises(TypeError, base64.standard_b64decode, "", altchars=b"") # Test with 'URL safe' alternative characters - eq(base64.urlsafe_b64decode(b'01a-b_cd'), b'\xd3V\xbeo\xf7\x1d') - self.assertRaises(TypeError, base64.urlsafe_b64decode, "") + eq(base64.urlsafe_b64decode('01a-b_cd'), b'\xd3V\xbeo\xf7\x1d') + self.assertRaises(TypeError, base64.urlsafe_b64decode, b"") def test_b64decode_error(self): - self.assertRaises(binascii.Error, base64.b64decode, b'abc') + self.assertRaises(binascii.Error, base64.b64decode, 'abc') def test_b32encode(self): eq = self.assertEqual - eq(base64.b32encode(b''), b'') - eq(base64.b32encode(b'\x00'), b'AA======') - eq(base64.b32encode(b'a'), b'ME======') - eq(base64.b32encode(b'ab'), b'MFRA====') - eq(base64.b32encode(b'abc'), b'MFRGG===') - eq(base64.b32encode(b'abcd'), b'MFRGGZA=') - eq(base64.b32encode(b'abcde'), b'MFRGGZDF') + eq(base64.b32encode(b''), '') + eq(base64.b32encode(b'\x00'), 'AA======') + eq(base64.b32encode(b'a'), 'ME======') + eq(base64.b32encode(b'ab'), 'MFRA====') + eq(base64.b32encode(b'abc'), 'MFRGG===') + eq(base64.b32encode(b'abcd'), 'MFRGGZA=') + eq(base64.b32encode(b'abcde'), 'MFRGGZDF') self.assertRaises(TypeError, base64.b32encode, "") def test_b32decode(self): eq = self.assertEqual - eq(base64.b32decode(b''), b'') - eq(base64.b32decode(b'AA======'), b'\x00') - eq(base64.b32decode(b'ME======'), b'a') - eq(base64.b32decode(b'MFRA===='), b'ab') - eq(base64.b32decode(b'MFRGG==='), b'abc') - eq(base64.b32decode(b'MFRGGZA='), b'abcd') - eq(base64.b32decode(b'MFRGGZDF'), b'abcde') - self.assertRaises(TypeError, base64.b32decode, "") + eq(base64.b32decode(''), b'') + eq(base64.b32decode('AA======'), b'\x00') + eq(base64.b32decode('ME======'), b'a') + eq(base64.b32decode('MFRA===='), b'ab') + eq(base64.b32decode('MFRGG==='), b'abc') + eq(base64.b32decode('MFRGGZA='), b'abcd') + eq(base64.b32decode('MFRGGZDF'), b'abcde') + self.assertRaises(TypeError, base64.b32decode, b"") def test_b32decode_casefold(self): eq = self.assertEqual - eq(base64.b32decode(b'', True), b'') - eq(base64.b32decode(b'ME======', True), b'a') - eq(base64.b32decode(b'MFRA====', True), b'ab') - eq(base64.b32decode(b'MFRGG===', True), b'abc') - eq(base64.b32decode(b'MFRGGZA=', True), b'abcd') - eq(base64.b32decode(b'MFRGGZDF', True), b'abcde') + eq(base64.b32decode('', True), b'') + eq(base64.b32decode('ME======', True), b'a') + eq(base64.b32decode('MFRA====', True), b'ab') + eq(base64.b32decode('MFRGG===', True), b'abc') + eq(base64.b32decode('MFRGGZA=', True), b'abcd') + eq(base64.b32decode('MFRGGZDF', True), b'abcde') # Lower cases - eq(base64.b32decode(b'me======', True), b'a') - eq(base64.b32decode(b'mfra====', True), b'ab') - eq(base64.b32decode(b'mfrgg===', True), b'abc') - eq(base64.b32decode(b'mfrggza=', True), b'abcd') - eq(base64.b32decode(b'mfrggzdf', True), b'abcde') + eq(base64.b32decode('me======', True), b'a') + eq(base64.b32decode('mfra====', True), b'ab') + eq(base64.b32decode('mfrgg===', True), b'abc') + eq(base64.b32decode('mfrggza=', True), b'abcd') + eq(base64.b32decode('mfrggzdf', True), b'abcde') # Expected exceptions self.assertRaises(TypeError, base64.b32decode, b'me======') # Mapping zero and one - eq(base64.b32decode(b'MLO23456'), b'b\xdd\xad\xf3\xbe') - eq(base64.b32decode(b'M1023456', map01=b'L'), b'b\xdd\xad\xf3\xbe') - eq(base64.b32decode(b'M1023456', map01=b'I'), b'b\x1d\xad\xf3\xbe') + eq(base64.b32decode('MLO23456'), b'b\xdd\xad\xf3\xbe') + eq(base64.b32decode('M1023456', map01='L'), b'b\xdd\xad\xf3\xbe') + eq(base64.b32decode('M1023456', map01='I'), b'b\x1d\xad\xf3\xbe') self.assertRaises(TypeError, base64.b32decode, b"", map01="") def test_b32decode_error(self): - self.assertRaises(binascii.Error, base64.b32decode, b'abc') - self.assertRaises(binascii.Error, base64.b32decode, b'ABCDEF==') + self.assertRaises(binascii.Error, base64.b32decode, 'abc') + self.assertRaises(binascii.Error, base64.b32decode, 'ABCDEF==') def test_b16encode(self): eq = self.assertEqual - eq(base64.b16encode(b'\x01\x02\xab\xcd\xef'), b'0102ABCDEF') - eq(base64.b16encode(b'\x00'), b'00') + eq(base64.b16encode(b'\x01\x02\xab\xcd\xef'), '0102ABCDEF') + eq(base64.b16encode(b'\x00'), '00') self.assertRaises(TypeError, base64.b16encode, "") def test_b16decode(self): eq = self.assertEqual - eq(base64.b16decode(b'0102ABCDEF'), b'\x01\x02\xab\xcd\xef') - eq(base64.b16decode(b'00'), b'\x00') + eq(base64.b16decode('0102ABCDEF'), b'\x01\x02\xab\xcd\xef') + eq(base64.b16decode('00'), b'\x00') # Lower case is not allowed without a flag - self.assertRaises(binascii.Error, base64.b16decode, b'0102abcdef') + self.assertRaises(binascii.Error, base64.b16decode, '0102abcdef') # Case fold - eq(base64.b16decode(b'0102abcdef', True), b'\x01\x02\xab\xcd\xef') - self.assertRaises(TypeError, base64.b16decode, "") + eq(base64.b16decode('0102abcdef', True), b'\x01\x02\xab\xcd\xef') + self.assertRaises(TypeError, base64.b16decode, b"") def test_ErrorHeritage(self): self.assertTrue(issubclass(binascii.Error, ValueError)) @@ -219,7 +219,7 @@ output = self.get_output('-t') self.assertSequenceEqual(output.splitlines(), ( b"b'Aladdin:open sesame'", - br"b'QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n'", + br"'QWxhZGRpbjpvcGVuIHNlc2FtZQ==\n'", b"b'Aladdin:open sesame'", )) Index: Lib/test/test_struct.py =================================================================== --- Lib/test/test_struct.py (revision 85127) +++ Lib/test/test_struct.py (working copy) @@ -213,7 +213,7 @@ expected = '%x' % expected if len(expected) & 1: expected = "0" + expected - expected = expected.encode('ascii') + expected = expected expected = unhexlify(expected) expected = (b"\x00" * (self.bytesize - len(expected)) + expected) Index: Lib/test/test_gettext.py =================================================================== --- Lib/test/test_gettext.py (revision 85127) +++ Lib/test/test_gettext.py (working copy) @@ -13,7 +13,7 @@ # has no sense, it would have if we were testing a parser (i.e. pygettext) # - Tests should have only one assert. -GNU_MO_DATA = b'''\ +GNU_MO_DATA = '''\ 3hIElQAAAAAGAAAAHAAAAEwAAAALAAAAfAAAAAAAAACoAAAAFQAAAKkAAAAjAAAAvwAAAKEAAADj AAAABwAAAIUBAAALAAAAjQEAAEUBAACZAQAAFgAAAN8CAAAeAAAA9gIAAKEAAAAVAwAABQAAALcD AAAJAAAAvQMAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABQAAAAYAAAACAAAAAFJh @@ -33,7 +33,7 @@ ciBUQUgKdHJnZ3JrZyB6cmZmbnRyIHBuZ255YnQgeXZvZW5lbC4AYmFjb24Ad2luayB3aW5rAA== ''' -UMO_DATA = b'''\ +UMO_DATA = '''\ 3hIElQAAAAACAAAAHAAAACwAAAAFAAAAPAAAAAAAAABQAAAABAAAAFEAAAAPAQAAVgAAAAQAAABm AQAAAQAAAAIAAAAAAAAAAAAAAAAAAAAAYWLDngBQcm9qZWN0LUlkLVZlcnNpb246IDIuMApQTy1S ZXZpc2lvbi1EYXRlOiAyMDAzLTA0LTExIDEyOjQyLTA0MDAKTGFzdC1UcmFuc2xhdG9yOiBCYXJy @@ -43,7 +43,7 @@ ZC1CeTogbWFudWFsbHkKAMKkeXoA ''' -MMO_DATA = b'''\ +MMO_DATA = '''\ 3hIElQAAAAABAAAAHAAAACQAAAADAAAALAAAAAAAAAA4AAAAeAEAADkAAAABAAAAAAAAAAAAAAAA UHJvamVjdC1JZC1WZXJzaW9uOiBObyBQcm9qZWN0IDAuMApQT1QtQ3JlYXRpb24tRGF0ZTogV2Vk IERlYyAxMSAwNzo0NDoxNSAyMDAyClBPLVJldmlzaW9uLURhdGU6IDIwMDItMDgtMTQgMDE6MTg6 @@ -65,13 +65,13 @@ if not os.path.isdir(LOCALEDIR): os.makedirs(LOCALEDIR) fp = open(MOFILE, 'wb') - fp.write(base64.decodebytes(GNU_MO_DATA)) + fp.write(base64.decodestring(GNU_MO_DATA)) fp.close() fp = open(UMOFILE, 'wb') - fp.write(base64.decodebytes(UMO_DATA)) + fp.write(base64.decodestring(UMO_DATA)) fp.close() fp = open(MMOFILE, 'wb') - fp.write(base64.decodebytes(MMO_DATA)) + fp.write(base64.decodestring(MMO_DATA)) fp.close() self.env = support.EnvironmentVarGuard() self.env['LANGUAGE'] = 'xx' Index: Lib/test/test_urllib2.py =================================================================== --- Lib/test/test_urllib2.py (revision 85127) +++ Lib/test/test_urllib2.py (working copy) @@ -1147,7 +1147,7 @@ self.assertFalse(http_handler.requests[0].has_header(auth_header)) userpass = bytes('%s:%s' % (user, password), "ascii") auth_hdr_value = ('Basic ' + - base64.encodebytes(userpass).strip().decode()) + base64.encodebytes(userpass).strip()) self.assertEqual(http_handler.requests[1].get_header(auth_header), auth_hdr_value) self.assertEqual(http_handler.requests[1].unredirected_hdrs[auth_header], Index: Lib/uu.py =================================================================== --- Lib/uu.py (revision 85127) +++ Lib/uu.py (working copy) @@ -59,9 +59,9 @@ # Open out_file if it is a pathname # if out_file == '-': - out_file = sys.stdout.buffer + out_file = sys.stdout elif isinstance(out_file, str): - out_file = open(out_file, 'wb') + out_file = open(out_file, 'w', encoding="ascii") # # Set defaults for name and mode # @@ -72,12 +72,12 @@ # # Write the data # - out_file.write(('begin %o %s\n' % ((mode & 0o777), name)).encode("ascii")) + out_file.write('begin %o %s\n' % ((mode & 0o777), name)) data = in_file.read(45) while len(data) > 0: out_file.write(binascii.b2a_uu(data)) data = in_file.read(45) - out_file.write(b' \nend\n') + out_file.write(' \nend\n') def decode(in_file, out_file=None, mode=None, quiet=False): @@ -86,9 +86,9 @@ # Open the input file, if needed. # if in_file == '-': - in_file = sys.stdin.buffer + in_file = sys.stdin elif isinstance(in_file, str): - in_file = open(in_file, 'rb') + in_file = open(in_file, 'r', encoding="ascii") # # Read until a begin is encountered or we've exhausted the file # @@ -96,10 +96,10 @@ hdr = in_file.readline() if not hdr: raise Error('No valid begin line found in input file') - if not hdr.startswith(b'begin'): + if not hdr.startswith('begin'): continue - hdrfields = hdr.split(b' ', 2) - if len(hdrfields) == 3 and hdrfields[0] == b'begin': + hdrfields = hdr.split(' ', 2) + if len(hdrfields) == 3 and hdrfields[0] == 'begin': try: int(hdrfields[1], 8) break @@ -107,7 +107,7 @@ pass if out_file is None: # If the filename isn't ASCII, what's up with that?!? - out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii") + out_file = hdrfields[2].rstrip(' \t\r\n\f') if os.path.exists(out_file): raise Error('Cannot overwrite existing file: %s' % out_file) if mode is None: @@ -130,7 +130,7 @@ # Main decoding loop # s = in_file.readline() - while s and s.strip(b' \t\r\n\f') != b'end': + while s and s.strip(' \t\r\n\f') != 'end': try: data = binascii.a2b_uu(s) except binascii.Error as v: Index: Lib/binhex.py =================================================================== --- Lib/binhex.py (revision 85127) +++ Lib/binhex.py (working copy) @@ -94,7 +94,7 @@ self.data = self.data[todo:] if not data: return - self.hqxdata = self.hqxdata + binascii.b2a_hqx(data) + self.hqxdata = self.hqxdata + binascii.b2a_hqx(data).encode("ascii") self._flush(0) def _flush(self, force): @@ -110,7 +110,7 @@ def close(self): if self.data: - self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data) + self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data).encode("ascii") self._flush(1) self.ofp.close() del self.ofp @@ -266,7 +266,7 @@ # while True: try: - decdatacur, self.eof = binascii.a2b_hqx(data) + decdatacur, self.eof = binascii.a2b_hqx(data.decode("ascii")) break except binascii.Incomplete: pass