Make bytes_repr return a string containing a b"" literal.
diff --git a/Include/Python-ast.h b/Include/Python-ast.h
index a702dbc..66d7b52 100644
--- a/Include/Python-ast.h
+++ b/Include/Python-ast.h
@@ -516,4 +516,3 @@
 alias_ty _Py_alias(identifier name, identifier asname, PyArena *arena);
 
 PyObject* PyAST_mod2obj(mod_ty t);
-
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py
index 4dee01b..83f6f93 100644
--- a/Lib/test/test_bytes.py
+++ b/Lib/test/test_bytes.py
@@ -69,9 +69,11 @@
         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])
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 09abaea..88e6585 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -733,65 +733,63 @@
     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;
     }
+    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 = '\'';
 
-    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;
+        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 *
diff --git a/Python/symtable.c b/Python/symtable.c
index 5f0290a..1d76e0d 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -1177,7 +1177,8 @@
 		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. */