]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #25357: Add an optional newline paramer to binascii.b2a_base64().
authorVictor Stinner <victor.stinner@gmail.com>
Sun, 11 Oct 2015 09:01:02 +0000 (11:01 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Sun, 11 Oct 2015 09:01:02 +0000 (11:01 +0200)
base64.b64encode() uses it to avoid a memory copy.

Doc/library/binascii.rst
Lib/base64.py
Lib/test/test_binascii.py
Misc/NEWS
Modules/binascii.c
Modules/clinic/binascii.c.h

index e3f134b53aca4c117b2a7f6ff7625db7a2f5c989..441aa57d52bdf0616b225be4d9ed96ea94a5e720 100644 (file)
@@ -52,11 +52,16 @@ The :mod:`binascii` module defines the following functions:
    than one line may be passed at a time.
 
 
-.. function:: b2a_base64(data)
+.. function:: b2a_base64(data, \*, newline=True)
 
    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.
+   value is the converted line, including a newline char if *newline* is
+   true. The length of *data* should be at most 57 to adhere to the
+   base64 standard.
+
+
+   .. versionchanged:: 3.6
+      Added the *newline* parameter.
 
 
 .. function:: a2b_qp(data, header=False)
index 640f787c73165c2d405f1ad457a2260836107d20..eb925cd4c55b91111e016a338cbf8ee3caee8572 100755 (executable)
@@ -58,8 +58,7 @@ def b64encode(s, altchars=None):
 
     The encoded byte string is returned.
     """
-    # Strip off the trailing newline
-    encoded = binascii.b2a_base64(s)[:-1]
+    encoded = binascii.b2a_base64(s, newline=False)
     if altchars is not None:
         assert len(altchars) == 2, repr(altchars)
         return encoded.translate(bytes.maketrans(b'+/', altchars))
index 8367afe0836888626bebcfaf505c22ff5dbd7936..0ab46bc3f3b25409f8d0a151719ebe73d6bba597 100644 (file)
@@ -262,6 +262,16 @@ class BinASCIITest(unittest.TestCase):
             # non-ASCII string
             self.assertRaises(ValueError, a2b, "\x80")
 
+    def test_b2a_base64_newline(self):
+        # Issue #25357: test newline parameter
+        b = self.type2test(b'hello')
+        self.assertEqual(binascii.b2a_base64(b),
+                         b'aGVsbG8=\n')
+        self.assertEqual(binascii.b2a_base64(b, newline=True),
+                         b'aGVsbG8=\n')
+        self.assertEqual(binascii.b2a_base64(b, newline=False),
+                         b'aGVsbG8=')
+
 
 class ArrayBinASCIITest(BinASCIITest):
     def type2test(self, s):
index 802f4b6920af84ed24fad3773ea6a0218897395f..e84ad1bf39515928e710579d1bb6d7321f34bd20 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -51,6 +51,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #25357: Add an optional newline paramer to binascii.b2a_base64().
+  base64.b64encode() uses it to avoid a memory copy.
+
 - Issue #24164: Objects that need calling ``__new__`` with keyword arguments,
   can now be pickled using pickle protocols older than protocol version 4.
 
index d920d2387106b0928d78f3a04a7f18009ff56da4..3e26a7a9d2143c7a25f4d48572d58de721f1348f 100644 (file)
@@ -528,21 +528,22 @@ binascii_a2b_base64_impl(PyModuleDef *module, Py_buffer *data)
 binascii.b2a_base64
 
     data: Py_buffer
-    /
+    *
+    newline: int(c_default="1") = True
 
 Base64-code line of data.
 [clinic start generated code]*/
 
 static PyObject *
-binascii_b2a_base64_impl(PyModuleDef *module, Py_buffer *data)
-/*[clinic end generated code: output=3cd61fbee2913285 input=14ec4e47371174a9]*/
+binascii_b2a_base64_impl(PyModuleDef *module, Py_buffer *data, int newline)
+/*[clinic end generated code: output=19e1dd719a890b50 input=7b2ea6fa38d8924c]*/
 {
     unsigned char *ascii_data, *bin_data;
     int leftbits = 0;
     unsigned char this_ch;
     unsigned int leftchar = 0;
     PyObject *rv;
-    Py_ssize_t bin_len;
+    Py_ssize_t bin_len, out_len;
 
     bin_data = data->buf;
     bin_len = data->len;
@@ -555,9 +556,12 @@ binascii_b2a_base64_impl(PyModuleDef *module, Py_buffer *data)
     }
 
     /* 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 )
+       "+2" leaves room for up to two pad characters.
+       Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */
+    out_len = bin_len*2 + 2;
+    if (newline)
+        out_len++;
+    if ( (rv=PyBytes_FromStringAndSize(NULL, out_len)) == NULL )
         return NULL;
     ascii_data = (unsigned char *)PyBytes_AS_STRING(rv);
 
@@ -581,7 +585,8 @@ binascii_b2a_base64_impl(PyModuleDef *module, Py_buffer *data)
         *ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2];
         *ascii_data++ = BASE64_PAD;
     }
-    *ascii_data++ = '\n';       /* Append a courtesy newline */
+    if (newline)
+        *ascii_data++ = '\n';       /* Append a courtesy newline */
 
     if (_PyBytes_Resize(&rv,
                        (ascii_data -
index e348beebaad179c87debebdef29600dd7b95902a..46cfb8ec3d844a72b6053ea0cc1944db2622faff 100644 (file)
@@ -93,26 +93,29 @@ exit:
 }
 
 PyDoc_STRVAR(binascii_b2a_base64__doc__,
-"b2a_base64($module, data, /)\n"
+"b2a_base64($module, /, data, *, newline=True)\n"
 "--\n"
 "\n"
 "Base64-code line of data.");
 
 #define BINASCII_B2A_BASE64_METHODDEF    \
-    {"b2a_base64", (PyCFunction)binascii_b2a_base64, METH_O, binascii_b2a_base64__doc__},
+    {"b2a_base64", (PyCFunction)binascii_b2a_base64, METH_VARARGS|METH_KEYWORDS, binascii_b2a_base64__doc__},
 
 static PyObject *
-binascii_b2a_base64_impl(PyModuleDef *module, Py_buffer *data);
+binascii_b2a_base64_impl(PyModuleDef *module, Py_buffer *data, int newline);
 
 static PyObject *
-binascii_b2a_base64(PyModuleDef *module, PyObject *arg)
+binascii_b2a_base64(PyModuleDef *module, PyObject *args, PyObject *kwargs)
 {
     PyObject *return_value = NULL;
+    static char *_keywords[] = {"data", "newline", NULL};
     Py_buffer data = {NULL, NULL};
+    int newline = 1;
 
-    if (!PyArg_Parse(arg, "y*:b2a_base64", &data))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|$i:b2a_base64", _keywords,
+        &data, &newline))
         goto exit;
-    return_value = binascii_b2a_base64_impl(module, &data);
+    return_value = binascii_b2a_base64_impl(module, &data, newline);
 
 exit:
     /* Cleanup for data */
@@ -516,4 +519,4 @@ exit:
 
     return return_value;
 }
-/*[clinic end generated code: output=b1a3cbf7660ebaa5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b15a24350d105251 input=a9049054013a1b77]*/