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'はい'.encode('utf-8') ==
u'はい'.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'はい'.encode('utf-8') ==
u'はい'.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