[pypy-svn] pypy default: (mfoord, antocuni) implement bytearray.fromhex

mfoord commits-noreply at bitbucket.org
Tue Jan 18 14:02:00 CET 2011


Author: Michael Foord <michael at voidspace.org.uk>
Branch: 
Changeset: r40847:2031592f79e7
Date: 2011-01-18 14:01 +0100
http://bitbucket.org/pypy/pypy/changeset/2031592f79e7/

Log:	(mfoord, antocuni) implement bytearray.fromhex

diff --git a/pypy/objspace/std/test/test_bytes.py b/pypy/objspace/std/test/test_bytes.py
--- a/pypy/objspace/std/test/test_bytes.py
+++ b/pypy/objspace/std/test/test_bytes.py
@@ -190,6 +190,26 @@
         assert b == 'abcdef'
         assert isinstance(b, bytearray)
 
+    def test_fromhex(self):
+        raises(TypeError, bytearray.fromhex, 9)
+
+        assert bytearray.fromhex('') == bytearray()
+        assert bytearray.fromhex(u'') == bytearray()
+
+        b = bytearray([0x1a, 0x2b, 0x30])
+        assert bytearray.fromhex('1a2B30') == b
+        assert bytearray.fromhex(u'1a2B30') == b
+        assert bytearray.fromhex(u'  1A 2B  30   ') == b
+        assert bytearray.fromhex(u'0000') == '\0\0'
+
+        raises(ValueError, bytearray.fromhex, u'a')
+        raises(ValueError, bytearray.fromhex, u'A')
+        raises(ValueError, bytearray.fromhex, u'rt')
+        raises(ValueError, bytearray.fromhex, u'1a b cd')
+        raises(ValueError, bytearray.fromhex, u'\x00')
+        raises(ValueError, bytearray.fromhex, u'12   \x00   34')
+        raises(UnicodeEncodeError, bytearray.fromhex, u'\u1234')
+
     def test_extend(self):
         b = bytearray('abc')
         b.extend(bytearray('def'))

diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py
--- a/pypy/objspace/std/bytearraytype.py
+++ b/pypy/objspace/std/bytearraytype.py
@@ -18,6 +18,7 @@
 from pypy.objspace.std.listtype import (
     list_append, list_extend)
 
+
 def getbytevalue(space, w_value):
     if space.isinstance_w(w_value, space.w_str):
         string = space.str_w(w_value)
@@ -104,6 +105,49 @@
             space.wrap('latin-1')]),
         w_dict])
 
+def _hex_digit_to_int(d):
+    val = ord(d)
+    if 47 < val < 58:
+        return val - 48
+    if 96 < val < 103:
+        return val - 87
+    return -1
+
+ at gateway.unwrap_spec(ObjSpace, W_Root, W_Root)
+def descr_fromhex(space, w_type, w_hexstring):
+    "bytearray.fromhex(string) -> bytearray\n\nCreate a bytearray object "
+    "from a string of hexadecimal numbers.\nSpaces between two numbers are "
+    "accepted.\nExample: bytearray.fromhex('B9 01EF') -> "
+    "bytearray(b'\\xb9\\x01\\xef')."
+    hexstring = space.str_w(w_hexstring)
+    hexstring = hexstring.lower()
+    data = []
+    length = len(hexstring)
+    i = -2
+    while True:
+        i += 2
+        while i < length and hexstring[i] == ' ':
+            i += 1
+        if i >= length:
+            break
+        if i+1 == length:
+            raise OperationError(space.w_ValueError, space.wrap(
+                "non-hexadecimal number found in fromhex() arg at position %d" % i))
+
+        top = _hex_digit_to_int(hexstring[i])
+        if top == -1:
+            raise OperationError(space.w_ValueError, space.wrap(
+                "non-hexadecimal number found in fromhex() arg at position %d" % i))
+        bot = _hex_digit_to_int(hexstring[i+1])
+        if bot == -1:
+            raise OperationError(space.w_ValueError, space.wrap(
+                "non-hexadecimal number found in fromhex() arg at position %d" % (i+1,)))
+        data.append(chr(top*16 + bot))
+
+    # in CPython bytearray.fromhex is a staticmethod, so
+    # we ignore w_type and always return a bytearray
+    return new_bytearray(space, space.w_bytearray, data)
+
 # ____________________________________________________________
 
 bytearray_typedef = StdTypeDef("bytearray",
@@ -114,5 +158,6 @@
     __new__ = gateway.interp2app(descr__new__),
     __hash__ = None,
     __reduce__ = gateway.interp2app(descr_bytearray__reduce__),
+    fromhex = gateway.interp2app(descr_fromhex, as_classmethod=True)
     )
 bytearray_typedef.registermethods(globals())


More information about the Pypy-commit mailing list