Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8cb6569

Browse files
committed
Implements issue #9951: Adds a hex() method to bytes, bytearray, & memoryview.
Also updates a few internal implementations of the same thing to use the new built-in code. Contributed by Arnon Yaari.
1 parent 644adc6 commit 8cb6569

15 files changed

Lines changed: 112 additions & 64 deletions

Doc/library/stdtypes.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,19 @@ the bytes type has an additional class method to read data in that format:
22892289
>>> bytes.fromhex('2Ef0 F1f2 ')
22902290
b'.\xf0\xf1\xf2'
22912291

2292+
A reverse conversion function exists to transform a bytes object into its
2293+
hexadecimal representation.
2294+
2295+
.. method:: bytes.hex()
2296+
2297+
Return a string object containing two hexadecimal digits for each
2298+
byte in the instance.
2299+
2300+
>>> b'\xf0\xf1\xf2'.hex()
2301+
'f0f1f2'
2302+
2303+
.. versionadded:: 3.5
2304+
22922305
Since bytes objects are sequences of integers (akin to a tuple), for a bytes
22932306
object *b*, ``b[0]`` will be an integer, while ``b[0:1]`` will be a bytes
22942307
object of length 1. (This contrasts with text strings, where both indexing
@@ -2344,6 +2357,19 @@ the bytearray type has an additional class method to read data in that format:
23442357
>>> bytearray.fromhex('2Ef0 F1f2 ')
23452358
bytearray(b'.\xf0\xf1\xf2')
23462359

2360+
A reverse conversion function exists to transform a bytearray object into its
2361+
hexadecimal representation.
2362+
2363+
.. method:: bytearray.hex()
2364+
2365+
Return a string object containing two hexadecimal digits for each
2366+
byte in the instance.
2367+
2368+
>>> bytearray(b'\xf0\xf1\xf2').hex()
2369+
'f0f1f2'
2370+
2371+
.. versionadded:: 3.5
2372+
23472373
Since bytearray objects are sequences of integers (akin to a list), for a
23482374
bytearray object *b*, ``b[0]`` will be an integer, while ``b[0:1]`` will be
23492375
a bytearray object of length 1. (This contrasts with text strings, where
@@ -3458,6 +3484,17 @@ copying.
34583484
supports all format strings, including those that are not in
34593485
:mod:`struct` module syntax.
34603486

3487+
.. method:: hex()
3488+
3489+
Return a string object containing two hexadecimal digits for each
3490+
byte in the buffer. ::
3491+
3492+
>>> m = memoryview(b"abc")
3493+
>>> m.hex()
3494+
'616263'
3495+
3496+
.. versionadded:: 3.5
3497+
34613498
.. method:: tolist()
34623499

34633500
Return the data in the buffer as a list of elements. ::

Doc/whatsnew/3.5.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ New built-in features:
8080

8181
* ``bytes % args``, ``bytearray % args``: :pep:`461` - Adding ``%`` formatting
8282
to bytes and bytearray
83+
* ``b'\xf0\x9f\x90\x8d'.hex()``, ``bytearray(b'\xf0\x9f\x90\x8d').hex()``,
84+
``memoryview(b'\xf0\x9f\x90\x8d').hex()``: :issue:`9951` - A ``hex`` method
85+
has been added to bytes, bytearray, and memoryview.
8386

8487
Implementation improvements:
8588

Lib/test/test_bytes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,14 @@ def test_fromhex(self):
301301
self.assertRaises(ValueError, self.type2test.fromhex, '\x00')
302302
self.assertRaises(ValueError, self.type2test.fromhex, '12 \x00 34')
303303

304+
def test_hex(self):
305+
self.assertRaises(TypeError, self.type2test.hex)
306+
self.assertRaises(TypeError, self.type2test.hex, 1)
307+
self.assertEquals(self.type2test(b"").hex(), "")
308+
self.assertEquals(bytearray([0x1a, 0x2b, 0x30]).hex(), '1a2b30')
309+
self.assertEquals(self.type2test(b"\x1a\x2b\x30").hex(), '1a2b30')
310+
self.assertEquals(memoryview(b"\x1a\x2b\x30").hex(), '1a2b30')
311+
304312
def test_join(self):
305313
self.assertEqual(self.type2test(b"").join([]), b"")
306314
self.assertEqual(self.type2test(b"").join([b""]), b"")

Lib/test/test_doctest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ def non_Python_modules(): r"""
659659
660660
>>> import builtins
661661
>>> tests = doctest.DocTestFinder().find(builtins)
662-
>>> 790 < len(tests) < 800 # approximate number of objects with docstrings
662+
>>> 790 < len(tests) < 810 # approximate number of objects with docstrings
663663
True
664664
>>> real_tests = [t for t in tests if len(t.examples) > 0]
665665
>>> len(real_tests) # objects that actually have doctests

Makefile.pre.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ PYTHON_OBJS= \
402402
Python/getopt.o \
403403
Python/pystrcmp.o \
404404
Python/pystrtod.o \
405+
Python/pystrhex.o \
405406
Python/dtoa.o \
406407
Python/formatter_unicode.o \
407408
Python/fileutils.o \
@@ -919,6 +920,7 @@ PYTHON_HEADERS= \
919920
$(srcdir)/Include/pystate.h \
920921
$(srcdir)/Include/pystrcmp.h \
921922
$(srcdir)/Include/pystrtod.h \
923+
$(srcdir)/Include/pystrhex.h \
922924
$(srcdir)/Include/pythonrun.h \
923925
$(srcdir)/Include/pythread.h \
924926
$(srcdir)/Include/pytime.h \

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,7 @@ Doug Wyatt
15471547
Robert Xiao
15481548
Florent Xicluna
15491549
Hirokazu Yamamoto
1550+
Arnon Yaari
15501551
Ka-Ping Yee
15511552
Jason Yeo
15521553
EungJun Yi

Misc/NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Core and Builtins
1111
-----------------
1212

1313
- Issue #24022: Fix tokenizer crash when processing undecodable source code.
14+
- Issue #9951: Added a hex() method to bytes, bytearray, and memoryview.
1415

1516
Library
1617
-------

Modules/sha1module.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "Python.h"
2020
#include "hashlib.h"
21+
#include "pystrhex.h"
2122

2223
/*[clinic input]
2324
module _sha1
@@ -364,32 +365,12 @@ SHA1Type_hexdigest_impl(SHA1object *self)
364365
{
365366
unsigned char digest[SHA1_DIGESTSIZE];
366367
struct sha1_state temp;
367-
PyObject *retval;
368-
Py_UCS1 *hex_digest;
369-
int i, j;
370368

371369
/* Get the raw (binary) digest value */
372370
temp = self->hash_state;
373371
sha1_done(&temp, digest);
374372

375-
/* Create a new string */
376-
retval = PyUnicode_New(SHA1_DIGESTSIZE * 2, 127);
377-
if (!retval)
378-
return NULL;
379-
hex_digest = PyUnicode_1BYTE_DATA(retval);
380-
381-
/* Make hex version of the digest */
382-
for(i=j=0; i<SHA1_DIGESTSIZE; i++) {
383-
unsigned char c;
384-
c = (digest[i] >> 4) & 0xf;
385-
hex_digest[j++] = Py_hexdigits[c];
386-
c = (digest[i] & 0xf);
387-
hex_digest[j++] = Py_hexdigits[c];
388-
}
389-
#ifdef Py_DEBUG
390-
assert(_PyUnicode_CheckConsistency(retval, 1));
391-
#endif
392-
return retval;
373+
return _Py_strhex((const char *)digest, SHA1_DIGESTSIZE);
393374
}
394375

395376
/*[clinic input]

Modules/sha256module.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Python.h"
2020
#include "structmember.h"
2121
#include "hashlib.h"
22+
#include "pystrhex.h"
2223

2324
/*[clinic input]
2425
module _sha256
@@ -454,32 +455,12 @@ SHA256Type_hexdigest_impl(SHAobject *self)
454455
{
455456
unsigned char digest[SHA_DIGESTSIZE];
456457
SHAobject temp;
457-
PyObject *retval;
458-
Py_UCS1 *hex_digest;
459-
int i, j;
460458

461459
/* Get the raw (binary) digest value */
462460
SHAcopy(self, &temp);
463461
sha_final(digest, &temp);
464462

465-
/* Create a new string */
466-
retval = PyUnicode_New(self->digestsize * 2, 127);
467-
if (!retval)
468-
return NULL;
469-
hex_digest = PyUnicode_1BYTE_DATA(retval);
470-
471-
/* Make hex version of the digest */
472-
for(i=j=0; i<self->digestsize; i++) {
473-
unsigned char c;
474-
c = (digest[i] >> 4) & 0xf;
475-
hex_digest[j++] = Py_hexdigits[c];
476-
c = (digest[i] & 0xf);
477-
hex_digest[j++] = Py_hexdigits[c];
478-
}
479-
#ifdef Py_DEBUG
480-
assert(_PyUnicode_CheckConsistency(retval, 1));
481-
#endif
482-
return retval;
463+
return _Py_strhex((const char *)digest, self->digestsize);
483464
}
484465

485466
/*[clinic input]

Modules/sha512module.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Python.h"
2020
#include "structmember.h"
2121
#include "hashlib.h"
22+
#include "pystrhex.h"
2223

2324
/*[clinic input]
2425
module _sha512
@@ -521,32 +522,12 @@ SHA512Type_hexdigest_impl(SHAobject *self)
521522
{
522523
unsigned char digest[SHA_DIGESTSIZE];
523524
SHAobject temp;
524-
PyObject *retval;
525-
Py_UCS1 *hex_digest;
526-
int i, j;
527525

528526
/* Get the raw (binary) digest value */
529527
SHAcopy(self, &temp);
530528
sha512_final(digest, &temp);
531529

532-
/* Create a new string */
533-
retval = PyUnicode_New(self->digestsize * 2, 127);
534-
if (!retval)
535-
return NULL;
536-
hex_digest = PyUnicode_1BYTE_DATA(retval);
537-
538-
/* Make hex version of the digest */
539-
for (i=j=0; i<self->digestsize; i++) {
540-
unsigned char c;
541-
c = (digest[i] >> 4) & 0xf;
542-
hex_digest[j++] = Py_hexdigits[c];
543-
c = (digest[i] & 0xf);
544-
hex_digest[j++] = Py_hexdigits[c];
545-
}
546-
#ifdef Py_DEBUG
547-
assert(_PyUnicode_CheckConsistency(retval, 1));
548-
#endif
549-
return retval;
530+
return _Py_strhex((const char *)digest, self->digestsize);
550531
}
551532

552533
/*[clinic input]

0 commit comments

Comments
 (0)