diff -r bf5a899a5d7c Doc/library/stdtypes.rst
--- a/Doc/library/stdtypes.rst Sun Apr 12 17:56:34 2015 -0400
+++ b/Doc/library/stdtypes.rst Mon Apr 13 15:44:02 2015 -0400
@@ -2289,6 +2289,17 @@
>>> bytes.fromhex('2Ef0 F1f2 ')
b'.\xf0\xf1\xf2'
+A reverse conversion function exists to transform a bytes object into its
+hexadecimal representation.
+
+.. method:: bytes.hex()
+
+ Return a string object containing two hexadecimal digits for each
+ byte in the instance.
+
+ >>> b'\xf0\xf1\xf2'.hex()
+ 'f0f1f2'
+
Since bytes objects are sequences of integers (akin to a tuple), for a bytes
object *b*, ``b[0]`` will be an integer, while ``b[0:1]`` will be a bytes
object of length 1. (This contrasts with text strings, where both indexing
@@ -2344,6 +2355,17 @@
>>> bytearray.fromhex('2Ef0 F1f2 ')
bytearray(b'.\xf0\xf1\xf2')
+A reverse conversion function exists to transform a bytearray object into its
+hexadecimal representation.
+
+.. method:: bytearray.hex()
+
+ Return a string object containing two hexadecimal digits for each
+ byte in the instance.
+
+ >>> b'\xf0\xf1\xf2'.hex()
+ 'f0f1f2'
+
Since bytearray objects are sequences of integers (akin to a list), for a
bytearray object *b*, ``b[0]`` will be an integer, while ``b[0:1]`` will be
a bytearray object of length 1. (This contrasts with text strings, where
@@ -3458,6 +3480,17 @@
supports all format strings, including those that are not in
:mod:`struct` module syntax.
+ .. method:: hex()
+
+ Return a string object containing two hexadecimal digits for each
+ byte in the buffer. ::
+
+ >>> m = memoryview(b"abc")
+ >>> m.hex()
+ '616263'
+
+ .. versionadded:: 3.5
+
.. method:: tolist()
Return the data in the buffer as a list of elements. ::
diff -r bf5a899a5d7c Lib/test/test_bytes.py
--- a/Lib/test/test_bytes.py Sun Apr 12 17:56:34 2015 -0400
+++ b/Lib/test/test_bytes.py Mon Apr 13 15:44:02 2015 -0400
@@ -301,6 +301,14 @@
self.assertRaises(ValueError, self.type2test.fromhex, '\x00')
self.assertRaises(ValueError, self.type2test.fromhex, '12 \x00 34')
+ def test_hex(self):
+ self.assertRaises(TypeError, self.type2test.hex)
+ self.assertRaises(TypeError, self.type2test.hex, 1)
+ self.assertEquals(self.type2test(b"").hex(), "")
+ self.assertEquals(bytearray([0x1a, 0x2b, 0x30]).hex(), '1a2b30')
+ self.assertEquals(self.type2test(b"\x1a\x2b\x30").hex(), '1a2b30')
+ self.assertEquals(memoryview(b"\x1a\x2b\x30").hex(), '1a2b30')
+
def test_join(self):
self.assertEqual(self.type2test(b"").join([]), b"")
self.assertEqual(self.type2test(b"").join([b""]), b"")
diff -r bf5a899a5d7c Lib/test/test_doctest.py
--- a/Lib/test/test_doctest.py Sun Apr 12 17:56:34 2015 -0400
+++ b/Lib/test/test_doctest.py Mon Apr 13 15:44:02 2015 -0400
@@ -659,7 +659,7 @@
>>> import builtins
>>> tests = doctest.DocTestFinder().find(builtins)
- >>> 790 >> 790 >> real_tests = [t for t in tests if len(t.examples) > 0]
>>> len(real_tests) # objects that actually have doctests
diff -r bf5a899a5d7c Makefile.pre.in
--- a/Makefile.pre.in Sun Apr 12 17:56:34 2015 -0400
+++ b/Makefile.pre.in Mon Apr 13 15:44:02 2015 -0400
@@ -402,6 +402,7 @@
Python/getopt.o \
Python/pystrcmp.o \
Python/pystrtod.o \
+ Python/pystrhex.o \
Python/dtoa.o \
Python/formatter_unicode.o \
Python/fileutils.o \
@@ -919,6 +920,7 @@
$(srcdir)/Include/pystate.h \
$(srcdir)/Include/pystrcmp.h \
$(srcdir)/Include/pystrtod.h \
+ $(srcdir)/Include/pystrhex.h \
$(srcdir)/Include/pythonrun.h \
$(srcdir)/Include/pythread.h \
$(srcdir)/Include/pytime.h \
diff -r bf5a899a5d7c Modules/sha1module.c
--- a/Modules/sha1module.c Sun Apr 12 17:56:34 2015 -0400
+++ b/Modules/sha1module.c Mon Apr 13 15:44:02 2015 -0400
@@ -18,6 +18,7 @@
#include "Python.h"
#include "hashlib.h"
+#include "pystrhex.h"
/*[clinic input]
module _sha1
@@ -364,32 +365,12 @@
{
unsigned char digest[SHA1_DIGESTSIZE];
struct sha1_state temp;
- PyObject *retval;
- Py_UCS1 *hex_digest;
- int i, j;
/* Get the raw (binary) digest value */
temp = self->hash_state;
sha1_done(&temp, digest);
- /* Create a new string */
- retval = PyUnicode_New(SHA1_DIGESTSIZE * 2, 127);
- if (!retval)
- return NULL;
- hex_digest = PyUnicode_1BYTE_DATA(retval);
-
- /* Make hex version of the digest */
- for(i=j=0; i> 4) & 0xf;
- hex_digest[j++] = Py_hexdigits[c];
- c = (digest[i] & 0xf);
- hex_digest[j++] = Py_hexdigits[c];
- }
-#ifdef Py_DEBUG
- assert(_PyUnicode_CheckConsistency(retval, 1));
-#endif
- return retval;
+ return _Py_strhex((const char *)digest, SHA1_DIGESTSIZE);
}
/*[clinic input]
diff -r bf5a899a5d7c Modules/sha256module.c
--- a/Modules/sha256module.c Sun Apr 12 17:56:34 2015 -0400
+++ b/Modules/sha256module.c Mon Apr 13 15:44:02 2015 -0400
@@ -19,6 +19,7 @@
#include "Python.h"
#include "structmember.h"
#include "hashlib.h"
+#include "pystrhex.h"
/*[clinic input]
module _sha256
@@ -454,32 +455,12 @@
{
unsigned char digest[SHA_DIGESTSIZE];
SHAobject temp;
- PyObject *retval;
- Py_UCS1 *hex_digest;
- int i, j;
/* Get the raw (binary) digest value */
SHAcopy(self, &temp);
sha_final(digest, &temp);
- /* Create a new string */
- retval = PyUnicode_New(self->digestsize * 2, 127);
- if (!retval)
- return NULL;
- hex_digest = PyUnicode_1BYTE_DATA(retval);
-
- /* Make hex version of the digest */
- for(i=j=0; idigestsize; i++) {
- unsigned char c;
- c = (digest[i] >> 4) & 0xf;
- hex_digest[j++] = Py_hexdigits[c];
- c = (digest[i] & 0xf);
- hex_digest[j++] = Py_hexdigits[c];
- }
-#ifdef Py_DEBUG
- assert(_PyUnicode_CheckConsistency(retval, 1));
-#endif
- return retval;
+ return _Py_strhex((const char *)digest, self->digestsize);
}
/*[clinic input]
diff -r bf5a899a5d7c Modules/sha512module.c
--- a/Modules/sha512module.c Sun Apr 12 17:56:34 2015 -0400
+++ b/Modules/sha512module.c Mon Apr 13 15:44:02 2015 -0400
@@ -19,6 +19,7 @@
#include "Python.h"
#include "structmember.h"
#include "hashlib.h"
+#include "pystrhex.h"
/*[clinic input]
module _sha512
@@ -521,32 +522,12 @@
{
unsigned char digest[SHA_DIGESTSIZE];
SHAobject temp;
- PyObject *retval;
- Py_UCS1 *hex_digest;
- int i, j;
/* Get the raw (binary) digest value */
SHAcopy(self, &temp);
sha512_final(digest, &temp);
- /* Create a new string */
- retval = PyUnicode_New(self->digestsize * 2, 127);
- if (!retval)
- return NULL;
- hex_digest = PyUnicode_1BYTE_DATA(retval);
-
- /* Make hex version of the digest */
- for (i=j=0; idigestsize; i++) {
- unsigned char c;
- c = (digest[i] >> 4) & 0xf;
- hex_digest[j++] = Py_hexdigits[c];
- c = (digest[i] & 0xf);
- hex_digest[j++] = Py_hexdigits[c];
- }
-#ifdef Py_DEBUG
- assert(_PyUnicode_CheckConsistency(retval, 1));
-#endif
- return retval;
+ return _Py_strhex((const char *)digest, self->digestsize);
}
/*[clinic input]
diff -r bf5a899a5d7c Objects/bytearrayobject.c
--- a/Objects/bytearrayobject.c Sun Apr 12 17:56:34 2015 -0400
+++ b/Objects/bytearrayobject.c Mon Apr 13 15:44:02 2015 -0400
@@ -5,6 +5,7 @@
#include "structmember.h"
#include "bytes_methods.h"
#include "bytesobject.h"
+#include "pystrhex.h"
/*[clinic input]
class bytearray "PyByteArrayObject *" "&PyByteArray_Type"
@@ -2868,6 +2869,19 @@
return NULL;
}
+PyDoc_STRVAR(hex__doc__,
+"B.hex() -> string\n\
+\n\
+Create a string of hexadecimal numbers from a bytearray object.\n\
+Example: bytearray([0xb9, 0x01, 0xef]).hex() -> 'b901ef'.");
+
+static PyObject *
+bytearray_hex(PyBytesObject *self)
+{
+ char* argbuf = PyByteArray_AS_STRING(self);
+ Py_ssize_t arglen = PyByteArray_GET_SIZE(self);
+ return _Py_strhex(argbuf, arglen);
+}
static PyObject *
_common_reduce(PyByteArrayObject *self, int proto)
@@ -2998,6 +3012,7 @@
BYTEARRAY_EXTEND_METHODDEF
{"find", (PyCFunction)bytearray_find, METH_VARARGS, find__doc__},
BYTEARRAY_FROMHEX_METHODDEF
+ {"hex", (PyCFunction)bytearray_hex, METH_NOARGS, hex__doc__},
{"index", (PyCFunction)bytearray_index, METH_VARARGS, index__doc__},
BYTEARRAY_INSERT_METHODDEF
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
diff -r bf5a899a5d7c Objects/bytesobject.c
--- a/Objects/bytesobject.c Sun Apr 12 17:56:34 2015 -0400
+++ b/Objects/bytesobject.c Mon Apr 13 15:44:02 2015 -0400
@@ -5,6 +5,7 @@
#include "Python.h"
#include "bytes_methods.h"
+#include "pystrhex.h"
#include
/*[clinic input]
@@ -3034,6 +3035,20 @@
return NULL;
}
+PyDoc_STRVAR(hex__doc__,
+"B.hex() -> string\n\
+\n\
+Create a string of hexadecimal numbers from a bytes object.\n\
+Example: b'\\xb9\\x01\\xef'.hex() -> 'b901ef'.");
+
+static PyObject *
+bytes_hex(PyBytesObject *self)
+{
+ char* argbuf = PyBytes_AS_STRING(self);
+ Py_ssize_t arglen = PyBytes_GET_SIZE(self);
+ return _Py_strhex(argbuf, arglen);
+}
+
static PyObject *
bytes_getnewargs(PyBytesObject *v)
{
@@ -3055,6 +3070,7 @@
expandtabs__doc__},
{"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__},
BYTES_FROMHEX_METHODDEF
+ {"hex", (PyCFunction)bytes_hex, METH_NOARGS, hex__doc__},
{"index", (PyCFunction)bytes_index, METH_VARARGS, index__doc__},
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
_Py_isalnum__doc__},
diff -r bf5a899a5d7c Objects/memoryobject.c
--- a/Objects/memoryobject.c Sun Apr 12 17:56:34 2015 -0400
+++ b/Objects/memoryobject.c Mon Apr 13 15:44:02 2015 -0400
@@ -1,6 +1,7 @@
/* Memoryview object implementation */
#include "Python.h"
+#include "pystrhex.h"
#include
@@ -2158,6 +2159,14 @@
}
static PyObject *
+memory_hex(PyMemoryViewObject *self, PyObject *dummy)
+{
+ Py_buffer *src = VIEW_ADDR(self);
+ CHECK_RELEASED(self);
+ return _Py_strhex(src->buf, src->len);
+}
+
+static PyObject *
memory_repr(PyMemoryViewObject *self)
{
if (self->flags & _Py_MEMORYVIEW_RELEASED)
@@ -3061,6 +3070,10 @@
"tobytes($self, /)\n--\n\
\n\
Return the data in the buffer as a byte string.");
+PyDoc_STRVAR(memory_hex_doc,
+"hex($self, /)\n--\n\
+\n\
+Return the data in the buffer as a string of hexadecimal numbers.");
PyDoc_STRVAR(memory_tolist_doc,
"tolist($self, /)\n--\n\
\n\
@@ -3073,6 +3086,7 @@
static PyMethodDef memory_methods[] = {
{"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc},
{"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc},
+ {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc},
{"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc},
{"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc},
{"__enter__", memory_enter, METH_NOARGS, NULL},
diff -r bf5a899a5d7c PCbuild/pythoncore.vcxproj
--- a/PCbuild/pythoncore.vcxproj Sun Apr 12 17:56:34 2015 -0400
+++ b/PCbuild/pythoncore.vcxproj Mon Apr 13 15:44:02 2015 -0400
@@ -147,6 +147,7 @@
+
@@ -376,6 +377,7 @@
+
diff -r bf5a899a5d7c PCbuild/pythoncore.vcxproj.filters
--- a/PCbuild/pythoncore.vcxproj.filters Sun Apr 12 17:56:34 2015 -0400
+++ b/PCbuild/pythoncore.vcxproj.filters Mon Apr 13 15:44:02 2015 -0400
@@ -243,6 +243,9 @@
Include
+
+ Include
+
Include
@@ -908,6 +911,9 @@
Python
+
+ Python
+
Python