Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r92312:965ce7010d54 Date: 2017-09-03 16:44 +0100 http://bitbucket.org/pypy/pypy/changeset/965ce7010d54/
Log: hg merge default diff --git a/lib-python/2.7/ctypes/test/test_byteswap.py b/lib-python/2.7/ctypes/test/test_byteswap.py --- a/lib-python/2.7/ctypes/test/test_byteswap.py +++ b/lib-python/2.7/ctypes/test/test_byteswap.py @@ -23,7 +23,6 @@ setattr(bits, "i%s" % i, 1) dump(bits) - @xfail def test_endian_short(self): if sys.byteorder == "little": self.assertIs(c_short.__ctype_le__, c_short) @@ -51,7 +50,6 @@ self.assertEqual(bin(s), "3412") self.assertEqual(s.value, 0x1234) - @xfail def test_endian_int(self): if sys.byteorder == "little": self.assertIs(c_int.__ctype_le__, c_int) @@ -80,7 +78,6 @@ self.assertEqual(bin(s), "78563412") self.assertEqual(s.value, 0x12345678) - @xfail def test_endian_longlong(self): if sys.byteorder == "little": self.assertIs(c_longlong.__ctype_le__, c_longlong) @@ -109,7 +106,6 @@ self.assertEqual(bin(s), "EFCDAB9078563412") self.assertEqual(s.value, 0x1234567890ABCDEF) - @xfail def test_endian_float(self): if sys.byteorder == "little": self.assertIs(c_float.__ctype_le__, c_float) @@ -128,7 +124,6 @@ self.assertAlmostEqual(s.value, math.pi, 6) self.assertEqual(bin(struct.pack(">f", math.pi)), bin(s)) - @xfail def test_endian_double(self): if sys.byteorder == "little": self.assertIs(c_double.__ctype_le__, c_double) @@ -156,7 +151,6 @@ self.assertIs(c_char.__ctype_le__, c_char) self.assertIs(c_char.__ctype_be__, c_char) - @xfail def test_struct_fields_1(self): if sys.byteorder == "little": base = BigEndianStructure @@ -192,7 +186,6 @@ pass self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)]) - @xfail def test_struct_struct(self): # nested structures with different byteorders @@ -221,7 +214,6 @@ self.assertEqual(s.point.x, 1) self.assertEqual(s.point.y, 2) - @xfail def test_struct_fields_2(self): # standard packing in struct uses no alignment. # So, we have to align using pad bytes. @@ -245,7 +237,6 @@ s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) self.assertEqual(bin(s1), bin(s2)) - @xfail def test_unaligned_nonnative_struct_fields(self): if sys.byteorder == "little": base = BigEndianStructure diff --git a/lib-python/2.7/ctypes/test/test_unaligned_structures.py b/lib-python/2.7/ctypes/test/test_unaligned_structures.py --- a/lib-python/2.7/ctypes/test/test_unaligned_structures.py +++ b/lib-python/2.7/ctypes/test/test_unaligned_structures.py @@ -37,10 +37,7 @@ for typ in byteswapped_structures: ## print >> sys.stderr, typ.value self.assertEqual(typ.value.offset, 1) - try: - o = typ() - except NotImplementedError as e: - self.skipTest(str(e)) # for PyPy + o = typ() o.value = 4 self.assertEqual(o.value, 4) diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py --- a/lib_pypy/_ctypes/pointer.py +++ b/lib_pypy/_ctypes/pointer.py @@ -141,6 +141,10 @@ ptr._buffer = tp._ffiarray(1, autofree=True) ptr._buffer[0] = obj._buffer result = ptr + elif isinstance(obj, bytes): + result = tp() + result._buffer[0] = buffer(obj)._pypy_raw_address() + return result elif not (isinstance(obj, _CData) and type(obj)._is_pointer_like()): raise TypeError("cast() argument 1 must be a pointer, not %s" % (type(obj),)) diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py --- a/lib_pypy/_ctypes/primitive.py +++ b/lib_pypy/_ctypes/primitive.py @@ -61,6 +61,54 @@ pyobj_container = GlobalPyobjContainer() +def swap_bytes(value, sizeof, typeof, get_or_set): + def swap_2(): + return ((value >> 8) & 0x00FF) | ((value << 8) & 0xFF00) + + def swap_4(): + return ((value & 0x000000FF) << 24) | \ + ((value & 0x0000FF00) << 8) | \ + ((value & 0x00FF0000) >> 8) | \ + ((value >> 24) & 0xFF) + + def swap_8(): + return ((value & 0x00000000000000FFL) << 56) | \ + ((value & 0x000000000000FF00L) << 40) | \ + ((value & 0x0000000000FF0000L) << 24) | \ + ((value & 0x00000000FF000000L) << 8) | \ + ((value & 0x000000FF00000000L) >> 8) | \ + ((value & 0x0000FF0000000000L) >> 24) | \ + ((value & 0x00FF000000000000L) >> 40) | \ + ((value >> 56) & 0xFF) + + def swap_double_float(typ): + from struct import pack, unpack + if get_or_set == 'set': + if sys.byteorder == 'little': + st = pack(''.join(['>', typ]), value) + else: + st = pack(''.join(['<', typ]), value) + return unpack(typ, st)[0] + else: + packed = pack(typ, value) + if sys.byteorder == 'little': + st = unpack(''.join(['>', typ]), packed) + else: + st = unpack(''.join(['<', typ]), packed) + return st[0] + + if typeof in ('c_float', 'c_float_le', 'c_float_be'): + return swap_double_float('f') + elif typeof in ('c_double', 'c_double_le', 'c_double_be'): + return swap_double_float('d') + else: + if sizeof == 2: + return swap_2() + elif sizeof == 4: + return swap_4() + elif sizeof == 8: + return swap_8() + def generic_xxx_p_from_param(cls, value): if value is None: return cls(None) @@ -265,6 +313,31 @@ def _as_ffi_pointer_(self, ffitype): return as_ffi_pointer(self, ffitype) result._as_ffi_pointer_ = _as_ffi_pointer_ + if name[-2:] != '_p' and name[-3:] not in ('_le', '_be') \ + and name not in ('c_wchar', '_SimpleCData', 'c_longdouble', 'c_bool', 'py_object'): + from sys import byteorder + if byteorder == 'big': + name += '_le' + swapped = self.__new__(self, name, bases, dct) + result.__ctype_le__ = swapped + result.__ctype_be__ = result + swapped.__ctype_be__ = result + swapped.__ctype_le__ = swapped + else: + name += '_be' + swapped = self.__new__(self, name, bases, dct) + result.__ctype_be__ = swapped + result.__ctype_le__ = result + swapped.__ctype_le__ = result + swapped.__ctype_be__ = swapped + from _ctypes import sizeof + def _getval(self): + return swap_bytes(self._buffer[0], sizeof(self), name, 'get') + def _setval(self, value): + d = result() + d.value = value + self._buffer[0] = swap_bytes(d.value, sizeof(self), name, 'set') + swapped.value = property(_getval, _setval) return result diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py --- a/lib_pypy/_ctypes/structure.py +++ b/lib_pypy/_ctypes/structure.py @@ -146,6 +146,7 @@ obj._buffer.__setattr__(self.name, arg) + def _set_shape(tp, rawfields, is_union=False): tp._ffistruct_ = _rawffi.Structure(rawfields, is_union, getattr(tp, '_pack_', 0)) @@ -240,18 +241,26 @@ res.__dict__['_index'] = -1 return res - class StructOrUnion(_CData, metaclass=StructOrUnionMeta): def __new__(cls, *args, **kwds): from _ctypes import union - self = super(_CData, cls).__new__(cls) - if ('_abstract_' in cls.__dict__ or cls is Structure + if ('_abstract_' in cls.__dict__ or cls is Structure or cls is union.Union): raise TypeError("abstract class") if hasattr(cls, '_swappedbytes_'): - raise NotImplementedError("missing in PyPy: structure/union with " - "swapped (non-native) byte ordering") + fields = [None] * len(cls._fields_) + for i in range(len(cls._fields_)): + if cls._fields_[i][1] == cls._fields_[i][1].__dict__.get('__ctype_be__', None): + swapped = cls._fields_[i][1].__dict__.get('__ctype_le__', cls._fields_[i][1]) + else: + swapped = cls._fields_[i][1].__dict__.get('__ctype_be__', cls._fields_[i][1]) + if len(cls._fields_[i]) < 3: + fields[i] = (cls._fields_[i][0], swapped) + else: + fields[i] = (cls._fields_[i][0], swapped, cls._fields_[i][2]) + names_and_fields(cls, fields, _CData, cls.__dict__.get('_anonymous_', None)) + self = super(_CData, cls).__new__(cls) if hasattr(cls, '_ffistruct_'): self.__dict__['_buffer'] = self._ffistruct_(autofree=True) return self diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst --- a/pypy/doc/build.rst +++ b/pypy/doc/build.rst @@ -119,8 +119,15 @@ To run untranslated tests, you need the Boehm garbage collector libgc. -On Debian and Ubuntu, this is the command to install all build-time -dependencies:: +On recent Debian and Ubuntu (like 17.04), this is the command to install +all build-time dependencies:: + + apt-get install gcc make libffi-dev pkg-config zlib1g-dev libbz2-dev \ + libsqlite3-dev libncurses5-dev libexpat1-dev libssl-dev libgdbm-dev \ + tk-dev libgc-dev python-cffi \ + liblzma-dev libncursesw5-dev # these two only needed on PyPy3 + +On older Debian and Ubuntu (12.04 to 16.04):: apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \ libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \ 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 @@ -548,6 +548,11 @@ or ``float`` subtypes. Currently PyPy does not support the ``__class__`` attribute assignment for any non heaptype subtype. +* In PyPy, module and class dictionaries are optimized under the assumption + that deleting attributes from them are rare. Because of this, e.g. + ``del foo.bar`` where ``foo`` is a module (or class) that contains the + function ``bar``, is significantly slower than CPython. + .. _`is ignored in PyPy`: http://bugs.python.org/issue14621 .. _`little point`: http://events.ccc.de/congress/2012/Fahrplan/events/5152.en.html .. _`#2072`: https://bitbucket.org/pypy/pypy/issue/2072/ diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py --- a/pypy/module/cpyext/test/test_eval.py +++ b/pypy/module/cpyext/test/test_eval.py @@ -366,3 +366,56 @@ ) excinfo = raises(RecursionError, module.call_recursive) assert 'while calling recurse' in str(excinfo.value) + + def test_build_class(self): + # make sure PyObject_Call generates a proper PyTypeObject, + # along the way verify that userslot has iter and next + module = self.import_extension('foo', [ + ("object_call", "METH_O", + ''' + return PyObject_Call((PyObject*)&PyType_Type, args, NULL); + '''), + ('iter', "METH_O", + ''' + if (NULL == args->ob_type->tp_iter) + { + PyErr_SetString(PyExc_TypeError, "NULL tp_iter"); + return NULL; + } + return args->ob_type->tp_iter(args); + '''), + ('next', "METH_O", + ''' + if (NULL == args->ob_type->tp_iternext) + { + PyErr_SetString(PyExc_TypeError, "NULL tp_iternext"); + return NULL; + } + return args->ob_type->tp_iternext(args); + '''),]) + def __init__(self, N): + self.N = N + self.i = 0 + + def __iter__(self): + return self + + def __next__(self): + if self.i < self.N: + i = self.i + self.i += 1 + return i + raise StopIteration + + d = {'__init__': __init__, '__iter__': __iter__, 'next': __next__, + '__next__': __next__} + C = module.object_call(('Iterable', (object,), d)) + c = C(5) + i = module.iter(c) + out = [] + try: + while 1: + out.append(module.next(i)) + except StopIteration: + pass + assert out == [0, 1, 2, 3, 4] diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -311,13 +311,18 @@ setattr(pto, slot_names[0], slot_func_helper) elif ((w_type is space.w_list or w_type is space.w_tuple) and slot_names[0] == 'c_tp_as_number'): - # XXX hack - hwo can we generalize this? The problem is method + # XXX hack - how can we generalize this? The problem is method # names like __mul__ map to more than one slot, and we have no # convenient way to indicate which slots CPython have filled # # We need at least this special case since Numpy checks that # (list, tuple) do __not__ fill tp_as_number pass + elif ((space.issubtype_w(w_type, space.w_bytes) or + space.issubtype_w(w_type, space.w_unicode)) and + slot_names[0] == 'c_tp_as_number'): + # like above but for any str type + pass else: assert len(slot_names) == 2 struct = getattr(pto, slot_names[0]) 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 @@ -122,3 +122,11 @@ else: space.delete(w_self, w_obj) return 0 + +@slot_function([PyObject], PyObject) +def slot_tp_iter(space, w_self): + return space.iter(w_self) + +@slot_function([PyObject], PyObject) +def slot_tp_iternext(space, w_self): + return space.next(w_self) diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py @@ -22,7 +22,6 @@ assert X._fields_ == [("a", c_int)] assert Y._fields_ == [("b", c_int)] assert Z._fields_ == [("a", c_int)] - assert Y._names_ == ['a', 'b'] def test_subclass_delayed(self): @@ -455,6 +454,39 @@ p = pointer(obj) assert p.contents._b_base_ is p + def test_swapped_bytes(self): + import sys + + for i in [c_short, c_int, c_long, c_longlong, + c_float, c_double, c_ushort, c_uint, + c_ulong, c_ulonglong]: + FIELDS = [ + ('n', i) + ] + + class Native(Structure): + _fields_ = FIELDS + + class Big(BigEndianStructure): + _fields_ = FIELDS + + class Little(LittleEndianStructure): + _fields_ = FIELDS + + def dostruct(c): + ba = create_string_buffer(sizeof(c)) + ms = c.from_buffer(ba) + ms.n = 0xff00 + return repr(ba[:]) + + if sys.byteorder == 'little': + assert dostruct(Native) == dostruct(Little) + assert dostruct(Native) != dostruct(Big) + else: + assert dostruct(Native) == dostruct(Big) + assert dostruct(Native) != dostruct(Little) + + class TestPointerMember(BaseCTypesTestChecker): def test_1(self): # a Structure with a POINTER field diff --git a/pypy/objspace/std/sliceobject.py b/pypy/objspace/std/sliceobject.py --- a/pypy/objspace/std/sliceobject.py +++ b/pypy/objspace/std/sliceobject.py @@ -132,6 +132,18 @@ else: return space.w_False + def descr_ne(self, space, w_other): + if space.is_w(self, w_other): + return space.w_False + if not isinstance(w_other, W_SliceObject): + return space.w_NotImplemented + if space.eq_w(self.w_start, w_other.w_start) and \ + space.eq_w(self.w_stop, w_other.w_stop) and \ + space.eq_w(self.w_step, w_other.w_step): + return space.w_False + else: + return space.w_True + def descr_lt(self, space, w_other): if space.is_w(self, w_other): return space.w_False # see comments in descr_eq() @@ -179,6 +191,7 @@ __reduce__ = gateway.interp2app(W_SliceObject.descr__reduce__), __eq__ = gateway.interp2app(W_SliceObject.descr_eq), + __ne__ = gateway.interp2app(W_SliceObject.descr_ne), __lt__ = gateway.interp2app(W_SliceObject.descr_lt), start = slicewprop('w_start'), diff --git a/pypy/objspace/std/test/test_sliceobject.py b/pypy/objspace/std/test/test_sliceobject.py --- a/pypy/objspace/std/test/test_sliceobject.py +++ b/pypy/objspace/std/test/test_sliceobject.py @@ -94,6 +94,7 @@ slice1 = slice(1, 2, 3) slice2 = slice(1, 2, 3) assert slice1 == slice2 + assert not slice1 != slice2 slice2 = slice(1, 2) assert slice1 != slice2 diff --git a/rpython/flowspace/test/test_objspace.py b/rpython/flowspace/test/test_objspace.py --- a/rpython/flowspace/test/test_objspace.py +++ b/rpython/flowspace/test/test_objspace.py @@ -839,15 +839,15 @@ return x[s] graph = self.codetest(myfunc) + @py.test.mark.xfail def test_unichr_constfold(self): - py.test.skip("not working") def myfunc(): return unichr(1234) graph = self.codetest(myfunc) assert graph.startblock.exits[0].target is graph.returnblock + @py.test.mark.xfail def test_unicode_constfold(self): - py.test.skip("not working for now") def myfunc(): return unicode("1234") graph = self.codetest(myfunc) diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -10,7 +10,7 @@ from rpython.jit.metainterp.optimizeopt.info import INFO_NONNULL, INFO_NULL from rpython.jit.metainterp.optimizeopt.util import _findall, make_dispatcher_method from rpython.jit.metainterp.resoperation import rop, ResOperation, opclasses,\ - OpHelpers + OpHelpers, AbstractResOp from rpython.rlib.rarithmetic import highest_bit from rpython.rtyper.lltypesystem import llmemory from rpython.rtyper import rclass @@ -490,6 +490,11 @@ def postprocess_GUARD_TRUE(self, op): box = self.get_box_replacement(op.getarg(0)) + if (isinstance(box, AbstractResOp) and + box.getopnum() == rop.INT_IS_TRUE): + # we can't use the (current) range analysis for this because + # "anything but 0" is not a valid range + self.pure_from_args(rop.INT_IS_ZERO, [box.getarg(0)], CONST_0) self.make_constant(box, CONST_1) def optimize_GUARD_FALSE(self, op): @@ -497,6 +502,11 @@ def postprocess_GUARD_FALSE(self, op): box = self.get_box_replacement(op.getarg(0)) + if (isinstance(box, AbstractResOp) and + box.getopnum() == rop.INT_IS_ZERO): + # we can't use the (current) range analysis for this because + # "anything but 0" is not a valid range + self.pure_from_args(rop.INT_IS_TRUE, [box.getarg(0)], CONST_1) self.make_constant(box, CONST_0) def optimize_ASSERT_NOT_NONE(self, op): diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -288,7 +288,6 @@ self.optimize_loop(ops, expected) def test_int_is_true_is_zero(self): - py.test.skip("XXX implement me") ops = """ [i0] i1 = int_is_true(i0) @@ -305,6 +304,22 @@ """ self.optimize_loop(ops, expected) + ops = """ + [i0] + i2 = int_is_zero(i0) + guard_false(i2) [] + i1 = int_is_true(i0) + guard_true(i1) [] + jump(i0) + """ + expected = """ + [i0] + i2 = int_is_zero(i0) + guard_false(i2) [] + jump(i0) + """ + self.optimize_loop(ops, expected) + def test_int_is_zero_int_is_true(self): ops = """ [i0] diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -400,7 +400,7 @@ return rop.can_raise(self.getopnum()) def is_foldable_guard(self): - return rop.is_foldable_guard(self.getopnun()) + return rop.is_foldable_guard(self.getopnum()) def is_primitive_array_access(self): """ Indicates that this operations loads/stores a diff --git a/rpython/jit/metainterp/test/test_bridgeopt.py b/rpython/jit/metainterp/test/test_bridgeopt.py --- a/rpython/jit/metainterp/test/test_bridgeopt.py +++ b/rpython/jit/metainterp/test/test_bridgeopt.py @@ -76,8 +76,11 @@ box_strategy = strategies.builds(InputArgInt) | strategies.builds(InputArgRef) -tuples = strategies.tuples(box_strategy, strategies.booleans()).filter( - lambda (box, known_class): isinstance(box, InputArgRef) or not known_class) +def _make_tup(box, known_class): + if isinstance(box, InputArgInt): + known_class = False + return box, known_class +tuples = strategies.builds(_make_tup, box_strategy, strategies.booleans()) boxes_known_classes = strategies.lists(tuples, min_size=1) @given(boxes_known_classes) diff --git a/rpython/translator/sandbox/rsandbox.py b/rpython/translator/sandbox/rsandbox.py --- a/rpython/translator/sandbox/rsandbox.py +++ b/rpython/translator/sandbox/rsandbox.py @@ -27,17 +27,20 @@ ll_read_not_sandboxed = rposix.external('read', [rffi.INT, rffi.CCHARP, rffi.SIZE_T], rffi.SIZE_T, - sandboxsafe=True) + sandboxsafe=True, + _nowrapper=True) ll_write_not_sandboxed = rposix.external('write', [rffi.INT, rffi.CCHARP, rffi.SIZE_T], rffi.SIZE_T, - sandboxsafe=True) + sandboxsafe=True, + _nowrapper=True) @signature(types.int(), types.ptr(rffi.CCHARP.TO), types.int(), returns=types.none()) def writeall_not_sandboxed(fd, buf, length): + fd = rffi.cast(rffi.INT, fd) while length > 0: size = rffi.cast(rffi.SIZE_T, length) count = rffi.cast(lltype.Signed, ll_write_not_sandboxed(fd, buf, size)) @@ -58,7 +61,8 @@ buflen = self.buflen with lltype.scoped_alloc(rffi.CCHARP.TO, buflen) as buf: buflen = rffi.cast(rffi.SIZE_T, buflen) - count = ll_read_not_sandboxed(self.fd, buf, buflen) + fd = rffi.cast(rffi.INT, self.fd) + count = ll_read_not_sandboxed(fd, buf, buflen) count = rffi.cast(lltype.Signed, count) if count <= 0: raise IOError _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit