[pypy-commit] pypy py3k: (chronitis) Implement bytes.fromhex().

amauryfa noreply at buildbot.pypy.org
Mon Nov 7 21:22:41 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r48880:02d89bbd9a31
Date: 2011-11-07 21:17 +0100
http://bitbucket.org/pypy/pypy/changeset/02d89bbd9a31/

Log:	(chronitis) Implement bytes.fromhex(). Thanks!

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
@@ -93,18 +93,13 @@
         return val - 87
     return -1
 
-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.unicode_w(w_hexstring)
+def _hexstring_to_array(space, s):
     data = []
-    length = len(hexstring)
+    length = len(s)
     i = -2
     while True:
         i += 2
-        while i < length and hexstring[i] == ' ':
+        while i < length and s[i] == ' ':
             i += 1
         if i >= length:
             break
@@ -112,16 +107,28 @@
             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])
+        top = _hex_digit_to_int(s[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])
+        bot = _hex_digit_to_int(s[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))
+    return data
 
+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')."
+    if not space.is_w(space.type(w_hexstring), space.w_unicode):
+        raise OperationError(space.w_TypeError, space.wrap(
+                "must be str, not %s" % space.type(w_hexstring).name))
+    hexstring = space.unicode_w(w_hexstring)
+    
+    data = _hexstring_to_array(space, hexstring)
     # 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)
diff --git a/pypy/objspace/std/stringtype.py b/pypy/objspace/std/stringtype.py
--- a/pypy/objspace/std/stringtype.py
+++ b/pypy/objspace/std/stringtype.py
@@ -342,6 +342,29 @@
         W_StringObject.__init__(w_obj, value)
         return w_obj
 
+def descr_fromhex(space, w_type, w_hexstring):
+    "bytes.fromhex(string) -> bytes\n"
+    "\n"
+    "Create a bytes object from a string of hexadecimal numbers.\n"
+    "Spaces between two numbers are accepted.\n"
+    "Example: bytes.fromhex('B9 01EF') -> bytes(b'\\xb9\\x01\\xef')."
+    from pypy.objspace.std.bytearraytype import _hexstring_to_array
+    if not space.is_w(space.type(w_hexstring), space.w_unicode):
+        raise OperationError(space.w_TypeError, space.wrap(
+                "must be str, not %s" % space.type(w_hexstring).name))
+    hexstring = space.unicode_w(w_hexstring)
+    chars = ''.join(_hexstring_to_array(space, hexstring))
+    if space.config.objspace.std.withrope:
+        from pypy.objspace.std.ropeobject import rope, W_RopeObject
+        w_obj = space.allocate_instance(W_RopeObject, w_type)
+        W_RopeObject.__init__(w_obj, rope.LiteralStringNode(chars))
+        return w_obj
+    else:
+        from pypy.objspace.std.stringobject import W_StringObject
+        w_obj = space.allocate_instance(W_StringObject, w_type)
+        W_StringObject.__init__(w_obj, chars)
+        return w_obj
+
 # ____________________________________________________________
 
 str_typedef = StdTypeDef("bytes",
@@ -349,7 +372,8 @@
     __doc__ = '''str(object) -> string
 
 Return a nice string representation of the object.
-If the argument is a string, the return value is the same object.'''
+If the argument is a string, the return value is the same object.''',
+    fromhex = gateway.interp2app(descr_fromhex, as_classmethod=True)
     )
 
 str_typedef.registermethods(globals())
diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py
--- a/pypy/objspace/std/test/test_stringobject.py
+++ b/pypy/objspace/std/test/test_stringobject.py
@@ -99,6 +99,14 @@
         import operator
         raises(TypeError, operator.mod, b"%s", (1,))
 
+    def test_fromhex(self):
+        assert bytes.fromhex("abcd") == b'\xab\xcd'
+        assert b''.fromhex("abcd") == b'\xab\xcd'
+        assert bytes.fromhex("ab cd  ef") == b'\xab\xcd\xef'
+        raises(TypeError, bytes.fromhex, b"abcd")
+        raises(TypeError, bytes.fromhex, True)
+        raises(ValueError, bytes.fromhex, "hello world")
+
     def test_split(self):
         assert b"".split() == []
         assert b"".split(b'x') == [b'']


More information about the pypy-commit mailing list