]> granicus.if.org Git - python/commitdiff
Make bytes_repr return a string containing a b"" literal.
authorGeorg Brandl <georg@python.org>
Sat, 24 Feb 2007 19:41:35 +0000 (19:41 +0000)
committerGeorg Brandl <georg@python.org>
Sat, 24 Feb 2007 19:41:35 +0000 (19:41 +0000)
Include/Python-ast.h
Lib/test/test_bytes.py
Objects/bytesobject.c
Python/symtable.c

index a702dbc2fb249fdde2a6fedd1955589d575ff126..66d7b52580ea6e569dee9f5b4d8729b799c34d8e 100644 (file)
@@ -516,4 +516,3 @@ keyword_ty _Py_keyword(identifier arg, expr_ty value, PyArena *arena);
 alias_ty _Py_alias(identifier name, identifier asname, PyArena *arena);
 
 PyObject* PyAST_mod2obj(mod_ty t);
-
index 4dee01b7f20e837b1435ce9a6cac684542190d79..83f6f93627f3d1c556f7ab74e08c03dc943d0144 100644 (file)
@@ -69,9 +69,11 @@ class BytesTest(unittest.TestCase):
         self.assertRaises(ValueError, bytes, [10**100])
 
     def test_repr(self):
-        self.assertEqual(repr(bytes()), "bytes()")
-        self.assertEqual(repr(bytes([0])), "bytes([0x00])")
-        self.assertEqual(repr(bytes([0, 1, 254, 255])), "bytes([0x00, 0x01, 0xfe, 0xff])")
+        self.assertEqual(repr(bytes()), "b''")
+        self.assertEqual(repr(bytes([0])), "b'\\0'")
+        self.assertEqual(repr(bytes([0, 1, 254, 255])), "b'\\0\\x01\\xfe\\xff'")
+        self.assertEqual(repr(bytes('abc')), "b'abc'")
+        self.assertEqual(repr(bytes("'")), "b'\\''")
 
     def test_compare(self):
         b1 = bytes([1, 2, 3])
index 09abaea97faa7732d91e8bd70fd5e21dda423a9d..88e65858c6c7650cdf1a8840e3a713ccaf15bd3c 100644 (file)
@@ -733,65 +733,63 @@ bytes_init(PyBytesObject *self, PyObject *args, PyObject *kwds)
     return -1;
 }
 
+/* Mostly copied from string_repr, but without the
+   "smart quote" functionality. */
 static PyObject *
 bytes_repr(PyBytesObject *self)
 {
-    PyObject *list;
-    PyObject *str;
-    PyObject *result;
-    int err;
-    int i;
-
-    if (self->ob_size == 0)
-        return PyString_FromString("bytes()");
-
-    list = PyList_New(0);
-    if (list == NULL)
+    size_t newsize = 3 + 4 * self->ob_size;
+    PyObject *v;
+    if (newsize > PY_SSIZE_T_MAX || newsize / 4 != self->ob_size) {
+        PyErr_SetString(PyExc_OverflowError,
+            "bytes object is too large to make repr");
         return NULL;
-
-    str = PyString_FromString("bytes([");
-    if (str == NULL)
-        goto error;
-
-    err = PyList_Append(list, str);
-    Py_DECREF(str);
-    if (err < 0)
-        goto error;
-
-    for (i = 0; i < self->ob_size; i++) {
-        char buffer[20];
-        sprintf(buffer, ", 0x%02x", (unsigned char) (self->ob_bytes[i]));
-        str = PyString_FromString((i == 0) ? buffer+2 : buffer);
-        if (str == NULL)
-            goto error;
-        err = PyList_Append(list, str);
-        Py_DECREF(str);
-        if (err < 0)
-            goto error;
     }
-
-    str = PyString_FromString("])");
-    if (str == NULL)
-        goto error;
-
-    err = PyList_Append(list, str);
-    Py_DECREF(str);
-    if (err < 0)
-        goto error;
-    
-    str = PyString_FromString("");
-    if (str == NULL)
-        goto error;
-
-    result = _PyString_Join(str, list);
-    Py_DECREF(str);
-    Py_DECREF(list);
-    return result;
-
- error:
-    /* Error handling when list != NULL  */
-    Py_DECREF(list);
-    return NULL;
+    v = PyString_FromStringAndSize((char *)NULL, newsize);
+    if (v == NULL) {
+        return NULL;
+    }
+    else {
+        register Py_ssize_t i;
+        register char c;
+        register char *p;
+        int quote = '\'';
+
+        p = PyString_AS_STRING(v);
+        *p++ = 'b';
+        *p++ = quote;
+        for (i = 0; i < self->ob_size; i++) {
+            /* There's at least enough room for a hex escape
+               and a closing quote. */
+            assert(newsize - (p - PyString_AS_STRING(v)) >= 5);
+            c = self->ob_bytes[i];
+            if (c == quote || c == '\\')
+                *p++ = '\\', *p++ = c;
+            else if (c == '\t')
+                *p++ = '\\', *p++ = 't';
+            else if (c == '\n')
+                *p++ = '\\', *p++ = 'n';
+            else if (c == '\r')
+                *p++ = '\\', *p++ = 'r';
+            else if (c == 0)
+                *p++ = '\\', *p++ = '0';
+            else if (c < ' ' || c >= 0x7f) {
+                /* For performance, we don't want to call
+                   PyOS_snprintf here (extra layers of
+                   function call). */
+                sprintf(p, "\\x%02x", c & 0xff);
+                                p += 4;
+            }
+            else
+                *p++ = c;
+        }
+        assert(newsize - (p - PyString_AS_STRING(v)) >= 1);
+        *p++ = quote;
+        *p = '\0';
+        _PyString_Resize(
+            &v, (p - PyString_AS_STRING(v)));
+        return v;
+    }
 }
 
 static PyObject *
index 5f0290afa1aab5da8df318655d3dbfa502d42856..1d76e0d025dafb8b3055cfb0b28a6fcf6274acde 100644 (file)
@@ -1177,7 +1177,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
                break;
         case Num_kind:
         case Str_kind:
-       case Ellipsis_kind:
+        case Bytes_kind:
+        case Ellipsis_kind:
                /* Nothing to do here. */
                break;
        /* The following exprs can be assignment targets. */