Author: Amaury Forgeot d'Arc <amaur...@gmail.com>
Branch: py3k
Changeset: r48838:c30f57c0a8d2
Date: 2011-10-26 12:29 +0200
http://bitbucket.org/pypy/pypy/changeset/c30f57c0a8d2/

Log:    Share code between bytes and bytearray constructors. Add support for
        bytes(unicode_string, encoding)

diff --git a/pypy/objspace/std/bytearrayobject.py 
b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -39,49 +39,6 @@
 
 registerimplementation(W_BytearrayObject)
 
-init_signature = Signature(['source', 'encoding', 'errors'], None, None)
-init_defaults = [None, None, None]
-
-def init__Bytearray(space, w_bytearray, __args__):
-    # this is on the silly side
-    w_source, w_encoding, w_errors = __args__.parse_obj(
-            None, 'bytearray', init_signature, init_defaults)
-
-    if w_source is None:
-        w_source = space.wrap('')
-    if w_encoding is None:
-        w_encoding = space.w_None
-    if w_errors is None:
-        w_errors = space.w_None
-
-    # Unicode argument
-    if not space.is_w(w_encoding, space.w_None):
-        from pypy.objspace.std.unicodetype import (
-            _get_encoding_and_errors, encode_object
-        )
-        encoding, errors = _get_encoding_and_errors(space, w_encoding, 
w_errors)
-
-        # if w_source is an integer this correctly raises a TypeError
-        # the CPython error message is: "encoding or errors without a string 
argument"
-        # ours is: "expected unicode, got int object"
-        w_source = encode_object(space, w_source, encoding, errors)
-
-    # Is it an int?
-    try:
-        count = space.int_w(w_source)
-    except OperationError, e:
-        if not e.match(space, space.w_TypeError):
-            raise
-    else:
-        if count < 0:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("bytearray negative count"))
-        w_bytearray.data = ['\0'] * count
-        return
-
-    data = makebytesdata_w(space, w_source)
-    w_bytearray.data = data
-
 def len__Bytearray(space, w_bytearray):
     result = len(w_bytearray.data)
     return wrapint(space, result)
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
@@ -14,6 +14,7 @@
     str_expandtabs, str_ljust, str_rjust, str_center, str_zfill,
     str_join, str_split, str_rsplit, str_partition, str_rpartition,
     str_splitlines, str_translate)
+from pypy.objspace.std.stringtype import makebytesdata_w
 from pypy.objspace.std.listtype import (
     list_append, list_extend)
 
@@ -61,6 +62,12 @@
 def descr__new__(space, w_bytearraytype, __args__):
     return new_bytearray(space,w_bytearraytype, [])
 
+@gateway.unwrap_spec(encoding='str_or_None', errors='str_or_None')
+def descr__init__(space, w_bytearray, w_source=gateway.NoneNotWrapped,
+                  encoding=None, errors=None):
+    data = makebytesdata_w(space, w_source, encoding, errors)
+    w_bytearray.data = data
+
 
 def descr_bytearray__reduce__(space, w_self):
     from pypy.objspace.std.bytearrayobject import W_BytearrayObject
@@ -125,6 +132,7 @@
 
 If the argument is a bytearray, the return value is the same object.''',
     __new__ = gateway.interp2app(descr__new__),
+    __init__ = gateway.interp2app(descr__init__),
     __hash__ = None,
     __reduce__ = gateway.interp2app(descr_bytearray__reduce__),
     fromhex = gateway.interp2app(descr_fromhex, as_classmethod=True)
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
@@ -271,7 +271,36 @@
             "byte must be in range(0, 256)"))
     return chr(value)
 
-def makebytesdata_w(space, w_source):
+def makebytesdata_w(space, w_source, encoding=None, errors=None):
+    # None value
+    if w_source is None:
+        if encoding is not None or errors is not None:
+            raise OperationError(space.w_TypeError, space.wrap(
+                    "encoding or errors without string argument"))
+        return []
+    # Is it an int?
+    try:
+        count = space.int_w(w_source)
+    except OperationError, e:
+        if not e.match(space, space.w_TypeError):
+            raise
+    else:
+        if count < 0:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("negative count"))
+        if encoding is not None or errors is not None:
+            raise OperationError(space.w_TypeError, space.wrap(
+                    "encoding or errors without string argument"))
+        return ['\0'] * count
+    # Unicode with encoding
+    if space.isinstance_w(w_source, space.w_unicode):
+        if encoding is None:
+            raise OperationError(space.w_TypeError, space.wrap(
+                    "string argument without an encoding"))
+        from pypy.objspace.std.unicodetype import encode_object
+        w_source = encode_object(space, w_source, encoding, errors)
+        # and continue with the encoded string
+
     # String-like argument
     try:
         string = space.bufferstr_new_w(w_source)
@@ -295,11 +324,13 @@
         data.append(value)
     return data
 
-def descr__new__(space, w_stringtype, w_source=gateway.NoneNotWrapped):
+@gateway.unwrap_spec(encoding='str_or_None', errors='str_or_None')
+def descr__new__(space, w_stringtype, w_source=gateway.NoneNotWrapped,
+                 encoding=None, errors=None):
     if (w_source and space.is_w(space.type(w_source), space.w_bytes) and
         space.is_w(w_stringtype, space.w_bytes)):
         return w_source
-    value = ''.join(makebytesdata_w(space, w_source))
+    value = ''.join(makebytesdata_w(space, w_source, encoding, errors))
     if space.config.objspace.std.withrope:
         from pypy.objspace.std.ropeobject import rope, W_RopeObject
         w_obj = space.allocate_instance(W_RopeObject, w_stringtype)
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
@@ -89,6 +89,12 @@
 
 class AppTestStringObject:
 
+    def test_constructor(self):
+        assert bytes() == b''
+        assert bytes(3) == b'\0\0\0'
+        assert bytes(b'abc') == b'abc'
+        assert bytes('abc', 'ascii') == b'abc'
+
     def test_format(self):
         import operator
         raises(TypeError, operator.mod, b"%s", (1,))
@@ -627,7 +633,8 @@
         assert b'a' in b'abc'
         assert b'ab' in b'abc'
         assert not b'd' in b'abc'
-        raises(TypeError, b'a'.__contains__, 1)
+        assert 97 in b'a'
+        raises(TypeError, b'a'.__contains__, 1.0)
 
     def test_decode(self):
         assert b'hello'.decode('ascii') == 'hello'
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to