[pypy-commit] pypy py3.5-byteformat: add __mod__ to W_BytesObject, use mod_format to format the bytes object

plan_rich pypy.commits at gmail.com
Wed Aug 31 02:59:06 EDT 2016


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5-byteformat
Changeset: r86762:e551d8bfa0da
Date: 2016-08-31 08:58 +0200
http://bitbucket.org/pypy/pypy/changeset/e551d8bfa0da/

Log:	add __mod__ to W_BytesObject, use mod_format to format the bytes
	object

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
@@ -494,9 +494,14 @@
     [_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:
+    if fmt_type != FORMAT_UNICODE:
         fmt = space.str_w(w_fmt)
         formatter = StringFormatter(space, fmt, values_w, w_valuedict)
         try:
@@ -505,25 +510,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(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_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
@@ -97,10 +97,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 +873,11 @@
                "73616e746120636c617573"
         assert bytes(64).hex() == "00"*64
 
+    def test_format(self):
+        assert eval("b'a%db' % 2") == eval("b'a2b'")
+        assert eval("b'00%.2f'").__mod__((0.01234)) == eval("b'000.01'")
+        assert eval("b'%04X' % 10") == eval("b'000A'")
+        assert eval("b'%c' % 48") == eval("b'0'")
+        assert eval("b'%c' % b'a'") == eval("b'a'")
+        assert eval("b'%b' % b'abc'") == eval("b'abc'")
+
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


More information about the pypy-commit mailing list