[pypy-commit] pypy default: document that in f(**d) d must contain only string keys
Author: Carl Friedrich Bolz Branch: Changeset: r91191:7f5084ffd6c2 Date: 2017-05-06 17:03 +0200 http://bitbucket.org/pypy/pypy/changeset/7f5084ffd6c2/ Log:document that in f(**d) d must contain only string keys diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -501,7 +501,11 @@ the rest is kept. If you return an unexpected string from ``__hex__()`` you get an exception (or a crash before CPython 2.7.13). -* PyPy3: ``__class__`` attritube assignment between heaptypes and non heaptypes. +* In PyPy, dictionaries passed as ``**kwargs`` can contain only string keys, + even if the called function takes ``**kwargs``. E.g. this code always + produces a ``TypeError``, no matter what ``f`` is: ``f(**{1: 2})``. + +* PyPy3: ``__class__`` attribute assignment between heaptypes and non heaptypes. CPython allows that for module subtypes, but not for e.g. ``int`` or ``float`` subtypes. Currently PyPy does not support the ``__class__`` attribute assignment for any non heaptype subtype. ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Bytearrays have amortized constant-time "del a[:n]" (backport branch py3.5-bytearray)
Author: Ronan Lamy Branch: Changeset: r91192:42c69a434735 Date: 2017-05-06 19:29 +0100 http://bitbucket.org/pypy/pypy/changeset/42c69a434735/ Log:Bytearrays have amortized constant-time "del a[:n]" (backport branch py3.5-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 @@ -4,54 +4,67 @@ import_from_mixin, newlist_hint, resizelist_hint, specialize) from rpython.rlib.buffer import Buffer from rpython.rlib.rstring import StringBuilder, ByteListBuilder -from rpython.rlib.debug import check_list_of_chars +from rpython.rlib.debug import check_list_of_chars, check_nonneg from rpython.rtyper.lltypesystem import rffi from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr, nonmoving_raw_ptr_for_resizable_list) +from rpython.rlib import jit from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec -from pypy.interpreter.signature import Signature from pypy.interpreter.typedef import TypeDef -from pypy.objspace.std.sliceobject import W_SliceObject +from pypy.objspace.std.sliceobject import W_SliceObject, unwrap_start_stop from pypy.objspace.std.stringmethods import StringMethods, _get_buffer +from pypy.objspace.std.stringmethods import _descr_getslice_slowpath from pypy.objspace.std.bytesobject import W_BytesObject from pypy.objspace.std.util import get_positive_index - class W_BytearrayObject(W_Root): import_from_mixin(StringMethods) +_KIND1 = "bytearray" +_KIND2 = "bytearray" def __init__(self, data): check_list_of_chars(data) -self.data = resizable_list_supporting_raw_ptr(data) +self._data = resizable_list_supporting_raw_ptr(data) +self._offset = 0 +# NOTE: the bytearray data is in 'self._data[self._offset:]' +check_nonneg(self._offset) +_tweak_for_tests(self) + +def getdata(self): +if self._offset > 0: +self._data = self._data[self._offset:] +self._offset = 0 +return self._data def __repr__(self): """representation for debugging purposes""" -return "%s(%s)" % (self.__class__.__name__, ''.join(self.data)) +return "%s(%s)" % (self.__class__.__name__, + ''.join(self._data[self._offset:])) def buffer_w(self, space, flags): -return BytearrayBuffer(self.data, False) +return BytearrayBuffer(self) def readbuf_w(self, space): -return BytearrayBuffer(self.data, True) +return BytearrayBuffer(self, readonly=True) def writebuf_w(self, space): -return BytearrayBuffer(self.data, False) +return BytearrayBuffer(self) def charbuf_w(self, space): -return ''.join(self.data) +return ''.join(self.getdata()) def bytearray_list_of_chars_w(self, space): -return self.data +return self.getdata() def nonmovable_carray(self, space): -return BytearrayBuffer(self.data, False).get_raw_address() +return BytearrayBuffer(self).get_raw_address() def _new(self, value): -if value is self.data: +if value is self._data: value = value[:] return W_BytearrayObject(value) @@ -65,17 +78,27 @@ return W_BytearrayObject([]) def _len(self): -return len(self.data) +return len(self._data) - self._offset + +def _fixindex(self, space, index, errmsg="bytearray index out of range"): +# for getitem/setitem/delitem of a single char +if index >= 0: +index += self._offset +if index >= len(self._data): +raise OperationError(space.w_IndexError, space.newtext(errmsg)) +else: +index += len(self._data)# count from the end +if index < self._offset: +raise OperationError(space.w_IndexError, space.newtext(errmsg)) +check_nonneg(index) +return index def _getitem_result(self, space, index): -try: -character = self.data[index] -except IndexError: -raise oefmt(space.w_IndexError, "bytearray index out of range") +character = self._data[self._fixindex(space, index)] return space.newint(ord(character)) def _val(self, space): -return self.data +return self.getdata() @staticmethod def _use_rstr_ops(space, w_other): @@ -152,11 +175,12 @@ return 1 def ord(self, space): -if len(self.data) != 1: +length = self._len() +if length != 1: raise oefmt(space.w_TypeError, "ord() expected a character, but string of length %d " -"found", len(self.data)) -return space.ne
[pypy-commit] pypy default: merge heads
Author: Ronan Lamy Branch: Changeset: r91193:df2a94c7ae6f Date: 2017-05-06 19:38 +0100 http://bitbucket.org/pypy/pypy/changeset/df2a94c7ae6f/ Log:merge heads diff --git a/include/README b/include/README --- a/include/README +++ b/include/README @@ -1,7 +1,11 @@ This directory contains all the include files needed to build cpython extensions with PyPy. Note that these are just copies of the original headers -that are in pypy/module/cpyext/include: they are automatically copied from -there during translation. +that are in pypy/module/cpyext/{include,parse}: they are automatically copied +from there during translation. -Moreover, pypy_decl.h and pypy_macros.h are automatically generated, also -during translation. +Moreover, some pypy-specific files are automatically generated, also during +translation. Currently they are: +* pypy_decl.h +* pypy_macros.h +* pypy_numpy.h +* pypy_structmember_decl.h diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -501,7 +501,11 @@ the rest is kept. If you return an unexpected string from ``__hex__()`` you get an exception (or a crash before CPython 2.7.13). -* PyPy3: ``__class__`` attritube assignment between heaptypes and non heaptypes. +* In PyPy, dictionaries passed as ``**kwargs`` can contain only string keys, + even if the called function takes ``**kwargs``. E.g. this code always + produces a ``TypeError``, no matter what ``f`` is: ``f(**{1: 2})``. + +* PyPy3: ``__class__`` attribute assignment between heaptypes and non heaptypes. CPython allows that for module subtypes, but not for e.g. ``int`` or ``float`` subtypes. Currently PyPy does not support the ``__class__`` attribute assignment for any non heaptype subtype. diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py --- a/pypy/module/__builtin__/compiling.py +++ b/pypy/module/__builtin__/compiling.py @@ -38,6 +38,8 @@ "compile() arg 3 must be 'exec', 'eval' or 'single'") if space.isinstance_w(w_source, space.gettypeobject(ast.W_AST.typedef)): +if flags & consts.PyCF_ONLY_AST: +return w_source ast_node = ast.mod.from_object(space, w_source) return ec.compiler.compile_ast(ast_node, filename, mode, flags) diff --git a/pypy/module/__builtin__/test/test_compile.py b/pypy/module/__builtin__/test/test_compile.py --- a/pypy/module/__builtin__/test/test_compile.py +++ b/pypy/module/__builtin__/test/test_compile.py @@ -50,7 +50,8 @@ co1 = compile('print 1', '', 'exec', _ast.PyCF_ONLY_AST) raises(TypeError, compile, co1, '', 'eval') co2 = compile('1+1', '', 'eval', _ast.PyCF_ONLY_AST) -compile(co2, '', 'eval') +tree = compile(co2, '', 'eval') +assert compile(co2, '', 'eval', _ast.PyCF_ONLY_AST) is co2 def test_leading_newlines(self): src = """ diff --git a/pypy/module/cpyext/test/test_userslots.py b/pypy/module/cpyext/test/test_userslots.py --- a/pypy/module/cpyext/test/test_userslots.py +++ b/pypy/module/cpyext/test/test_userslots.py @@ -47,6 +47,33 @@ w_year = space.getattr(w_obj, space.newtext('year')) assert space.int_w(w_year) == 1 +def test_descr_slots(self, space, api): +w_descr = space.appexec([], """(): +class Descr(object): +def __get__(self, obj, type): +return 42 +def __set__(self, obj, value): +obj.append('set') +def __delete__(self, obj): +obj.append('del') +return Descr() +""") +w_descrtype = space.type(w_descr) +py_descr = make_ref(space, w_descr) +py_descrtype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_descrtype)) +w_obj = space.newlist([]) +py_obj = make_ref(space, w_obj) +w_res = generic_cpy_call(space, py_descrtype.c_tp_descr_get, + py_descr, py_obj, py_obj) +assert space.int_w(w_res) == 42 +assert generic_cpy_call( +space, py_descrtype.c_tp_descr_set, +py_descr, py_obj, make_ref(space, space.w_None)) == 0 +assert generic_cpy_call( +space, py_descrtype.c_tp_descr_set, +py_descr, py_obj, None) == 0 +assert space.eq_w(w_obj, space.wrap(['set', 'del'])) + class AppTestUserSlots(AppTestCpythonExtensionBase): def test_tp_hash_from_python(self): # to see that the functions are being used, diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py --- a/pypy/module/cpyext/userslot.py +++ b/pypy/module/cpyext/userslot.py @@ -109,4 +109,14 @@ def slot_tp_getattr(space, w_obj1, w_obj2): return space.getattr(w_obj1, w_obj2) +@slot_function([PyObject, PyObject, PyObject], PyObject) +def slot_tp_descr_get(space, w_self, w_obj, w_type)
[pypy-commit] pypy PyBuffer-backport: Fix bytearray
Author: Ronan Lamy Branch: PyBuffer-backport Changeset: r91195:dc72a659d99a Date: 2017-05-06 19:50 +0100 http://bitbucket.org/pypy/pypy/changeset/dc72a659d99a/ Log:Fix 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 @@ -2,18 +2,19 @@ from rpython.rlib.objectmodel import ( import_from_mixin, newlist_hint, resizelist_hint, specialize) -from rpython.rlib.buffer import Buffer from rpython.rlib.rstring import StringBuilder, ByteListBuilder from rpython.rlib.debug import check_list_of_chars, check_nonneg from rpython.rtyper.lltypesystem import rffi from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr, nonmoving_raw_ptr_for_resizable_list) from rpython.rlib import jit +from rpython.rlib.buffer import Buffer from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec from pypy.interpreter.typedef import TypeDef +from pypy.interpreter.buffer import SimpleView from pypy.objspace.std.sliceobject import W_SliceObject, unwrap_start_stop from pypy.objspace.std.stringmethods import StringMethods, _get_buffer from pypy.objspace.std.stringmethods import _descr_getslice_slowpath @@ -46,7 +47,7 @@ ''.join(self._data[self._offset:])) def buffer_w(self, space, flags): -return BytearrayBuffer(self) +return SimpleView(BytearrayBuffer(self)) def readbuf_w(self, space): return BytearrayBuffer(self, readonly=True) diff --git a/pypy/objspace/std/stringmethods.py b/pypy/objspace/std/stringmethods.py --- a/pypy/objspace/std/stringmethods.py +++ b/pypy/objspace/std/stringmethods.py @@ -812,4 +812,4 @@ return [selfvalue[start + i*step] for i in range(sl)] def _get_buffer(space, w_obj): -return space.buffer_w(w_obj, space.BUF_SIMPLE) +return space.buffer_w(w_obj, space.BUF_SIMPLE).as_readbuf() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy PyBuffer-backport: hg merge default
Author: Ronan Lamy Branch: PyBuffer-backport Changeset: r91194:9d07ac7eaf1a Date: 2017-05-06 19:40 +0100 http://bitbucket.org/pypy/pypy/changeset/9d07ac7eaf1a/ Log:hg merge default diff --git a/include/README b/include/README --- a/include/README +++ b/include/README @@ -1,7 +1,11 @@ This directory contains all the include files needed to build cpython extensions with PyPy. Note that these are just copies of the original headers -that are in pypy/module/cpyext/include: they are automatically copied from -there during translation. +that are in pypy/module/cpyext/{include,parse}: they are automatically copied +from there during translation. -Moreover, pypy_decl.h and pypy_macros.h are automatically generated, also -during translation. +Moreover, some pypy-specific files are automatically generated, also during +translation. Currently they are: +* pypy_decl.h +* pypy_macros.h +* pypy_numpy.h +* pypy_structmember_decl.h diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst --- a/pypy/doc/cpython_differences.rst +++ b/pypy/doc/cpython_differences.rst @@ -501,7 +501,11 @@ the rest is kept. If you return an unexpected string from ``__hex__()`` you get an exception (or a crash before CPython 2.7.13). -* PyPy3: ``__class__`` attritube assignment between heaptypes and non heaptypes. +* In PyPy, dictionaries passed as ``**kwargs`` can contain only string keys, + even if the called function takes ``**kwargs``. E.g. this code always + produces a ``TypeError``, no matter what ``f`` is: ``f(**{1: 2})``. + +* PyPy3: ``__class__`` attribute assignment between heaptypes and non heaptypes. CPython allows that for module subtypes, but not for e.g. ``int`` or ``float`` subtypes. Currently PyPy does not support the ``__class__`` attribute assignment for any non heaptype subtype. diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py --- a/pypy/module/__builtin__/compiling.py +++ b/pypy/module/__builtin__/compiling.py @@ -38,6 +38,8 @@ "compile() arg 3 must be 'exec', 'eval' or 'single'") if space.isinstance_w(w_source, space.gettypeobject(ast.W_AST.typedef)): +if flags & consts.PyCF_ONLY_AST: +return w_source ast_node = ast.mod.from_object(space, w_source) return ec.compiler.compile_ast(ast_node, filename, mode, flags) diff --git a/pypy/module/__builtin__/test/test_compile.py b/pypy/module/__builtin__/test/test_compile.py --- a/pypy/module/__builtin__/test/test_compile.py +++ b/pypy/module/__builtin__/test/test_compile.py @@ -50,7 +50,8 @@ co1 = compile('print 1', '', 'exec', _ast.PyCF_ONLY_AST) raises(TypeError, compile, co1, '', 'eval') co2 = compile('1+1', '', 'eval', _ast.PyCF_ONLY_AST) -compile(co2, '', 'eval') +tree = compile(co2, '', 'eval') +assert compile(co2, '', 'eval', _ast.PyCF_ONLY_AST) is co2 def test_leading_newlines(self): src = """ diff --git a/pypy/module/cpyext/test/test_userslots.py b/pypy/module/cpyext/test/test_userslots.py --- a/pypy/module/cpyext/test/test_userslots.py +++ b/pypy/module/cpyext/test/test_userslots.py @@ -47,6 +47,33 @@ w_year = space.getattr(w_obj, space.newtext('year')) assert space.int_w(w_year) == 1 +def test_descr_slots(self, space, api): +w_descr = space.appexec([], """(): +class Descr(object): +def __get__(self, obj, type): +return 42 +def __set__(self, obj, value): +obj.append('set') +def __delete__(self, obj): +obj.append('del') +return Descr() +""") +w_descrtype = space.type(w_descr) +py_descr = make_ref(space, w_descr) +py_descrtype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_descrtype)) +w_obj = space.newlist([]) +py_obj = make_ref(space, w_obj) +w_res = generic_cpy_call(space, py_descrtype.c_tp_descr_get, + py_descr, py_obj, py_obj) +assert space.int_w(w_res) == 42 +assert generic_cpy_call( +space, py_descrtype.c_tp_descr_set, +py_descr, py_obj, make_ref(space, space.w_None)) == 0 +assert generic_cpy_call( +space, py_descrtype.c_tp_descr_set, +py_descr, py_obj, None) == 0 +assert space.eq_w(w_obj, space.wrap(['set', 'del'])) + class AppTestUserSlots(AppTestCpythonExtensionBase): def test_tp_hash_from_python(self): # to see that the functions are being used, diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py --- a/pypy/module/cpyext/userslot.py +++ b/pypy/module/cpyext/userslot.py @@ -109,4 +109,14 @@ def slot_tp_getattr(space, w_obj1, w_obj2): return space.getattr(w_obj1, w_obj2) +@slot_function([PyObject, PyObject, PyObject], PyObject) +def slot_tp_descr_get(space,
[pypy-commit] pypy PyBuffer-backport: Add space.byte_w()
Author: Ronan Lamy Branch: PyBuffer-backport Changeset: r91196:97f60ebf3ec0 Date: 2017-05-06 20:42 +0100 http://bitbucket.org/pypy/pypy/changeset/97f60ebf3ec0/ Log:Add space.byte_w() diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1654,6 +1654,23 @@ def fsencode_or_none_w(self, w_obj): return None if self.is_none(w_obj) else self.fsencode_w(w_obj) +def byte_w(self, w_obj): +""" +Convert an index-like object to an interp-level char + +Used for app-level code like "bytearray(b'abc')[0] = 42". +""" +if self.isinstance_w(w_obj, self.w_bytes): +string = self.bytes_w(w_obj) +if len(string) != 1: +raise oefmt(self.w_ValueError, "string must be of size 1") +return string[0] +value = self.getindex_w(w_obj, None) +if not 0 <= value < 256: +# this includes the OverflowError in case the long is too large +raise oefmt(self.w_ValueError, "byte must be in range(0, 256)") +return chr(value) + def int_w(self, w_obj, allow_conversion=True): """ Unwrap an app-level int object into an interpret-level int. 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 @@ -415,7 +415,7 @@ else: idx = space.getindex_w(w_index, space.w_IndexError, "bytearray index") -newvalue = getbytevalue(space, w_other) +newvalue = space.byte_w(w_other) self._data[self._fixindex(space, idx)] = newvalue def descr_delitem(self, space, w_idx): @@ -442,7 +442,7 @@ _shrink_after_delete_from_start, self) def descr_append(self, space, w_item): -self._data.append(getbytevalue(space, w_item)) +self._data.append(space.byte_w(w_item)) def descr_extend(self, space, w_other): if isinstance(w_other, W_BytearrayObject): @@ -452,10 +452,9 @@ def descr_insert(self, space, w_idx, w_other): where = space.int_w(w_idx) -val = getbytevalue(space, w_other) data = self.getdata() -length = len(data) -index = get_positive_index(where, length) +index = get_positive_index(where, len(data)) +val = space.byte_w(w_other) data.insert(index, val) @unwrap_spec(w_idx=WrappedDefault(-1)) @@ -552,20 +551,6 @@ # -def getbytevalue(space, w_value): -if space.isinstance_w(w_value, space.w_bytes): -string = space.bytes_w(w_value) -if len(string) != 1: -raise oefmt(space.w_ValueError, "string must be of size 1") -return string[0] - -value = space.getindex_w(w_value, None) -if not 0 <= value < 256: -# this includes the OverflowError in case the long is too large -raise oefmt(space.w_ValueError, "byte must be in range(0, 256)") -return chr(value) - - def new_bytearray(space, w_bytearraytype, data): w_obj = space.allocate_instance(W_BytearrayObject, w_bytearraytype) W_BytearrayObject.__init__(w_obj, data) @@ -594,8 +579,7 @@ if not e.match(space, space.w_StopIteration): raise break -value = getbytevalue(space, w_item) -data.append(value) +data.append(space.byte_w(w_item)) extended += 1 if extended < length_hint: resizelist_hint(data, extended) diff --git a/pypy/objspace/std/test/test_memoryobject.py b/pypy/objspace/std/test/test_memoryobject.py --- a/pypy/objspace/std/test/test_memoryobject.py +++ b/pypy/objspace/std/test/test_memoryobject.py @@ -27,7 +27,8 @@ v[0:3] = v[2:5] assert data == bytearray(eval("b'23f3fg'")) exc = raises(ValueError, "v[2] = 'spam'") -assert str(exc.value) == "cannot modify size of memoryview object" +assert str(exc.value) in ("cannot modify size of memoryview object", + "string must be of size 1") exc = raises(NotImplementedError, "v[0:2:2] = 'spam'") assert str(exc.value) == "" ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit