Author: Richard Plangger <[email protected]>
Branch: py3.5
Changeset: r86774:daec70259c2e
Date: 2016-08-31 13:35 +0200
http://bitbucket.org/pypy/pypy/changeset/daec70259c2e/

Log:    merge byte format for bytes & bytearray

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
@@ -21,6 +21,7 @@
 from pypy.objspace.std.stringmethods import StringMethods, _get_buffer
 from pypy.objspace.std.bytesobject import W_BytesObject
 from pypy.objspace.std.util import get_positive_index
+from pypy.objspace.std.formatting import mod_format, FORMAT_BYTEARRAY
 
 NON_HEX_MSG = "non-hexadecimal number found in fromhex() arg at position %d"
 
@@ -446,6 +447,9 @@
     def descr_hex(self, space):
         return _array_to_hexstring(space, self.data, len(self.data), True)
 
+    def descr_mod(self, space, w_values):
+        return mod_format(space, self, w_values, fmt_type=FORMAT_BYTEARRAY)
+
     @staticmethod
     def _iter_getitem_result(self, space, index):
         assert isinstance(self, W_BytearrayObject)
@@ -599,6 +603,9 @@
     def __mul__():
         """x.__mul__(n) <==> x*n"""
 
+    def __mod__():
+        """x.__mod__(y) <==> x % y"""
+
     def __ne__():
         """x.__ne__(y) <==> x!=y"""
 
@@ -1099,6 +1106,8 @@
                              doc=BytearrayDocstrings.__setitem__.__doc__),
     __delitem__ = interp2app(W_BytearrayObject.descr_delitem,
                              doc=BytearrayDocstrings.__delitem__.__doc__),
+    __mod__ = interp2app(W_BytearrayObject.descr_mod,
+                           doc=BytearrayDocstrings.__mod__.__doc__),
 
     append = interp2app(W_BytearrayObject.descr_append,
                         doc=BytearrayDocstrings.append.__doc__),
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -14,6 +14,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.objspace.std.stringmethods import StringMethods
 from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
+from pypy.objspace.std.formatting import mod_format, FORMAT_BYTES
 
 
 class W_AbstractBytesObject(W_Root):
@@ -394,6 +395,12 @@
         of the specified width. The string S is never truncated.
         """
 
+    def descr_mod(self, space, w_values):
+        """S % values -> string
+
+        Format bytes objects
+        """
+
 class W_BytesObject(W_AbstractBytesObject):
     import_from_mixin(StringMethods)
     _immutable_fields_ = ['_value']
@@ -663,6 +670,9 @@
         from pypy.objspace.std.bytearrayobject import _array_to_hexstring
         return _array_to_hexstring(space, StringBuffer(self._value))
 
+    def descr_mod(self, space, w_values):
+        return mod_format(space, self, w_values, fmt_type=FORMAT_BYTES)
+
     @staticmethod
     def _iter_getitem_result(self, space, index):
         assert isinstance(self, W_BytesObject)
@@ -803,6 +813,8 @@
     __mul__ = interpindirect2app(W_AbstractBytesObject.descr_mul),
     __rmul__ = interpindirect2app(W_AbstractBytesObject.descr_rmul),
 
+    __mod__ = interpindirect2app(W_AbstractBytesObject.descr_mod),
+
     __getitem__ = interpindirect2app(W_AbstractBytesObject.descr_getitem),
 
     capitalize = interpindirect2app(W_AbstractBytesObject.descr_capitalize),
diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py
--- a/pypy/objspace/std/formatting.py
+++ b/pypy/objspace/std/formatting.py
@@ -438,7 +438,7 @@
             self.std_wp(s)
 
         def fmt_r(self, w_value):
-            self.std_wp(self.space.unicode_w(self.space.repr(w_value)))
+            self.fmt_a(w_value)
 
         def fmt_a(self, w_value):
             from pypy.objspace.std.unicodeobject import ascii_from_object
@@ -477,6 +477,31 @@
                                     "character code not in range(256)")
                     self.std_wp(s)
 
+        def fmt_b(self, w_value):
+            space = self.space
+            # cpython explicitly checks for bytes & bytearray
+            if space.isinstance_w(w_value, space.w_bytes):
+                self.std_wp(space.bytes_w(w_value))
+                return
+            if space.isinstance_w(w_value, space.w_bytearray):
+                buf = w_value.buffer_w(space, 0)
+                # convert the array of the buffer to a py 2 string
+                self.std_wp(buf.as_str())
+                return
+
+            w_bytes_method = space.lookup(w_value, "__bytes__")
+            if w_bytes_method is not None:
+                w_bytes = space.get_and_call_function(w_bytes_method, w_value)
+                if not space.isinstance_w(w_bytes, space.w_bytes):
+                    raise oefmt(space.w_TypeError,
+                                "__bytes__ returned non-bytes (type '%T')", 
w_bytes)
+                self.std_wp(space.bytes_w(w_bytes))
+                return
+
+            raise oefmt(space.w_TypeError,
+                    "requires bytes, or an object that" \
+                    "implements __bytes__, not '%T'", w_value)
+
     return StringFormatter
 
 
@@ -494,10 +519,18 @@
     [_name[-1] for _name in dir(StringFormatter)
                if len(_name) == 5 and _name.startswith('fmt_')])
 
-def format(space, w_fmt, values_w, w_valuedict, do_unicode):
+FORMAT_STR = 0
+FORMAT_UNICODE = 1
+FORMAT_BYTES = 2
+FORMAT_BYTEARRAY = 3
+
+def format(space, w_fmt, values_w, w_valuedict, fmt_type):
     "Entry point"
-    if not do_unicode:
-        fmt = space.str_w(w_fmt)
+    if fmt_type != FORMAT_UNICODE:
+        if fmt_type == FORMAT_BYTEARRAY:
+            fmt = w_fmt.buffer_w(space, 0).as_str()
+        else:
+            fmt = space.str_w(w_fmt)
         formatter = StringFormatter(space, fmt, values_w, w_valuedict)
         try:
             result = formatter.format()
@@ -505,25 +538,29 @@
             # fall through to the unicode case
             pass
         else:
+            if fmt_type == FORMAT_BYTES:
+                return space.newbytes(result)
+            elif fmt_type == FORMAT_BYTEARRAY:
+                return space.newbytearray([c for c in result])
             return space.wrap(result)
     fmt = space.unicode_w(w_fmt)
     formatter = UnicodeFormatter(space, fmt, values_w, w_valuedict)
     result = formatter.format()
     return space.wrap(result)
 
-def mod_format(space, w_format, w_values, do_unicode=False):
+def mod_format(space, w_format, w_values, fmt_type=FORMAT_STR):
     if space.isinstance_w(w_values, space.w_tuple):
         values_w = space.fixedview(w_values)
-        return format(space, w_format, values_w, None, do_unicode)
+        return format(space, w_format, values_w, None, fmt_type)
     else:
         # we check directly for dict to avoid obscure checking
         # in simplest case
         if space.isinstance_w(w_values, space.w_dict) or \
            (space.lookup(w_values, '__getitem__') and
            not space.isinstance_w(w_values, space.w_unicode)):
-            return format(space, w_format, [w_values], w_values, do_unicode)
+            return format(space, w_format, [w_values], w_values, fmt_type)
         else:
-            return format(space, w_format, [w_values], None, do_unicode)
+            return format(space, w_format, [w_values], None, fmt_type)
 
 # ____________________________________________________________
 # Formatting helpers
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -346,6 +346,9 @@
     def newbytes(self, s):
         return W_BytesObject(s)
 
+    def newbytearray(self, l):
+        return W_BytearrayObject(l)
+
     def newunicode(self, uni):
         return W_UnicodeObject(uni)
 
diff --git a/pypy/objspace/std/test/test_bytearrayobject.py 
b/pypy/objspace/std/test/test_bytearrayobject.py
--- a/pypy/objspace/std/test/test_bytearrayobject.py
+++ b/pypy/objspace/std/test/test_bytearrayobject.py
@@ -1,6 +1,7 @@
+# coding: utf-8
+
 from pypy import conftest
 
-
 class AppTestBytesArray:
     def setup_class(cls):
         cls.w_runappdirect = cls.space.wrap(conftest.option.runappdirect)
@@ -527,3 +528,20 @@
     def test_hex(self):
         assert bytearray(b'santa claus').hex() == "73616e746120636c617573"
 
+    def test_format(self):
+        """
+        assert bytearray(b'a%db') % 2 == b'a2b'
+        assert bytearray(b'00%.2f').__mod__((0.01234,)) == b'000.01'
+        assert bytearray(b'%04X') % 10 == b'000A'
+        assert bytearray(b'%c') % 48 == b'0'
+        assert bytearray(b'%c') % b'a' == b'a'
+        """
+
+    def test_format_b(self):
+        """
+        assert bytearray(b'%b') % b'abc' == b'abc'
+        assert bytearray(b'%b') % u'&#12399;&#12356;'.encode('utf-8') == 
u'&#12399;&#12356;'.encode('utf-8')
+        raises(TypeError, 'bytearray(b"%b") % 3.14')
+        raises(TypeError, 'bytearray(b"%b") % "hello world"')
+        assert bytearray(b'%b %b') % (b'a', bytearray(b'f f e')) == b'a f f e'
+        """
diff --git a/pypy/objspace/std/test/test_bytesobject.py 
b/pypy/objspace/std/test/test_bytesobject.py
--- a/pypy/objspace/std/test/test_bytesobject.py
+++ b/pypy/objspace/std/test/test_bytesobject.py
@@ -1,3 +1,4 @@
+# coding: utf-8
 class TestW_BytesObject:
 
     def teardown_method(self, method):
@@ -97,10 +98,6 @@
         assert bytes('abc', 'ascii') == b'abc'
         assert bytes(set(b'foo')) in (b'fo', b'of')
 
-    def test_format(self):
-        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'
@@ -877,3 +874,20 @@
                "73616e746120636c617573"
         assert bytes(64).hex() == "00"*64
 
+    def test_format(self):
+        """
+        assert b'a%db' % 2 == b'a2b'
+        assert b'00%.2f'.__mod__((0.01234,)) == b'000.01'
+        assert b'%04X' % 10 == b'000A'
+        assert b'%c' % 48 == b'0'
+        assert b'%c' % b'a' == b'a'
+        """
+
+    def test_format_b(self):
+        """
+        assert b'%b' % b'abc' == b'abc'
+        assert b'%b' % u'&#12399;&#12356;'.encode('utf-8') == 
u'&#12399;&#12356;'.encode('utf-8')
+        raises(TypeError, 'b"%b" % 3.14')
+        raises(TypeError, 'b"%b" % "hello world"')
+        assert b'%b %b' % (b'a', bytearray(b'f f e')) == b'a f f e'
+        """
diff --git a/pypy/objspace/std/unicodeobject.py 
b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -15,7 +15,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.module.unicodedata import unicodedb
 from pypy.objspace.std import newformat
-from pypy.objspace.std.formatting import mod_format
+from pypy.objspace.std.formatting import mod_format, FORMAT_UNICODE
 from pypy.objspace.std.stringmethods import StringMethods
 from pypy.objspace.std.util import IDTAG_SPECIAL, IDTAG_SHIFT
 
@@ -392,7 +392,7 @@
                                        self)
 
     def descr_mod(self, space, w_values):
-        return mod_format(space, self, w_values, do_unicode=True)
+        return mod_format(space, self, w_values, fmt_type=FORMAT_UNICODE)
 
     def descr_translate(self, space, w_table):
         selfvalue = self._value
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to