Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r88005:dd3f94d97955 Date: 2016-10-31 16:40 +0000 http://bitbucket.org/pypy/pypy/changeset/dd3f94d97955/
Log: hg merge default diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py --- a/lib_pypy/cffi/cparser.py +++ b/lib_pypy/cffi/cparser.py @@ -334,6 +334,8 @@ realtype, quals = self._get_type_and_quals( decl.type, name=decl.name, partial_length_ok=True) self._declare('typedef ' + decl.name, realtype, quals=quals) + elif decl.__class__.__name__ == 'Pragma': + pass # skip pragma, only in pycparser 2.15 else: raise api.CDefError("unrecognized construct", decl) except api.FFIError as e: diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py --- a/lib_pypy/cffi/model.py +++ b/lib_pypy/cffi/model.py @@ -519,10 +519,18 @@ smallest_value = min(self.enumvalues) largest_value = max(self.enumvalues) else: - raise api.CDefError("%r has no values explicitly defined: " - "refusing to guess which integer type it is " - "meant to be (unsigned/signed, int/long)" - % self._get_c_name()) + import warnings + try: + # XXX! The goal is to ensure that the warnings.warn() + # will not suppress the warning. We want to get it + # several times if we reach this point several times. + __warningregistry__.clear() + except NameError: + pass + warnings.warn("%r has no values explicitly defined; " + "guessing that it is equivalent to 'unsigned int'" + % self._get_c_name()) + smallest_value = largest_value = 0 if smallest_value < 0: # needs a signed type sign = 1 candidate1 = PrimitiveType("int") diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py --- a/lib_pypy/cffi/setuptools_ext.py +++ b/lib_pypy/cffi/setuptools_ext.py @@ -1,4 +1,5 @@ import os +import sys try: basestring @@ -74,8 +75,13 @@ Add py_limited_api to kwds if setuptools >= 26 is in use. Do not alter the setting if it already exists. Setuptools takes care of ignoring the flag on Python 2 and PyPy. + + CPython itself should ignore the flag in a debugging version + (by not listing .abi3.so in the extensions it supports), but + it doesn't so far, creating troubles. That's why we check + for "not sys.flags.debug". (http://bugs.python.org/issue28401) """ - if 'py_limited_api' not in kwds: + if 'py_limited_api' not in kwds and not sys.flags.debug: import setuptools try: setuptools_major_version = int(setuptools.__version__.partition('.')[0]) diff --git a/pypy/doc/release-pypy2.7-v5.6.0.rst b/pypy/doc/release-pypy2.7-v5.6.0.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-pypy2.7-v5.6.0.rst @@ -0,0 +1,142 @@ +============ +PyPy2.7 v5.6 +============ + +We have released PyPy2.7 v5.6, about two months after PyPy2.7 v5.4. +This new PyPy2.7 release includes the upstream stdlib version 2.7.12. + +We continue to make incremental improvements to our C-API +compatability layer (cpyext). We pass all but a few of the tests in the +upstream numpy `test suite`_. + +Work proceeds at a good pace on the PyPy3.5 +version due to a grant_ from the Mozilla Foundation, and some of those +changes have been backported to PyPy2.7 where relevant + +We changed ``timeit`` to now report average +- standard deviation, which is +better than the misleading minimum value reported in CPython. + +XXX + +As always, this release fixed many issues and bugs raised by the +growing community of PyPy users. We strongly recommend updating. + +You can download the PyPy2.7 v5.6 release here: + + http://pypy.org/download.html + +We would like to thank our donors for the continued support of the PyPy +project. + +We would also like to thank our contributors and +encourage new people to join the project. PyPy has many +layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation +improvements, tweaking popular `modules`_ to run on pypy, or general `help`_ +with making RPython's JIT even better. + +.. _`test suite`: https://bitbucket.org/pypy/pypy/wiki/Adventures%20in%20cpyext%20compatibility +.. _cffi: https://cffi.readthedocs.org +.. _grant: https://morepypy.blogspot.com/2016/08/pypy-gets-funding-from-mozilla-for.html +.. _`PyPy`: http://doc.pypy.org +.. _`RPython`: https://rpython.readthedocs.org +.. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly +.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html + +What is PyPy? +============= + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison) +due to its integrated tracing JIT compiler. + +We also welcome developers of other `dynamic languages`_ to see what RPython +can do for them. + +This release supports: + + * **x86** machines on most common operating systems + (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD) + + * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux, + + * big- and little-endian variants of **PPC64** running Linux, + + * **s390x** running Linux + +.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org +.. _`dynamic languages`: http://pypyjs.org + +Other Highlights (since 5.4 released Aug 31, 2016) +========================================================= + +* New features + * Allow tests run with `-A` to find `libm.so` even if it is a script not a + dynamically loadable file + * Backport fixes to rposix on windows from py2.5 + * Allow user-defined ``__getitem__`` on subclasses of ``str`` and ``unicode`` + * Add ``inode`` to ``scandir()`` on posix systems + * Support more attributes on ``super`` + * Issue #2386: non-latin1 unicode keys were ignored in ``unicode.format(**d)`` + * Restore the ability to translate with CPython + * Update to CFFI 1.8.4 + * Support the new buffer protocol in cpyext and numpypy + * Add ``rposix.sync()`` + * Support full-precision nanosecond times in os.stat() + * Add documentation about the assembler backends to RPYthon + * Search for the stdlibs from the libpypy shared object rather than the pypy-c exe, + changes downstream packaging requirments + * Add ``try_inline``, like ``always_inline`` and ``dont_inline`` to RPython + * Reject ``'a'.strip(buffer(' '))`` like cpython (the argument to strip must + be ``str`` or ``unicode``) + * Allow ``warning.warn(('something', 1), Warning)`` like on CPython + * Refactor ``rclock`` and add some more ``CLOCK_xxx`` constants on + relevant platforms + * Backport the ``'faulthandler`` module from py3.5 + * Improve the error message when trying to call a method where the ``self`` + parameter is missing in the definition + * Implement ``rposix.cpu_count`` + * Support translation on FreeBSD running on PowerPC + * Implement ``__rmod__`` on ``str`` and ``unicode`` types + * Issue warnings for stricter handling of ``__new__``, ``__init__`` args + +* Bug Fixes + * Tweak a float comparison with 0 in `backendopt.inline` to avoid rounding errors + * Fix translation of the sandbox + * Fix for an issue where `unicode.decode('utf8', 'custom_replace')` messed up + the last byte of a unicode string sometimes + * fix some calls to functions through window's COM interface + * fix minor leak when the C call to socketpair() fails + * make sure (-1.0 + 0j).__hash__(), (-1.0).__hash__() returns -2 + * Fix for an issue where PyBytesResize was called on a fresh pyobj + * Fix bug in codewriter about passing the ``exitswitch`` variable to a call + * Don't crash in ``merge_if_blocks`` if the values are symbolics + * Issue #2325/2361: __class__ assignment between two classes with the same + slots + * Issue #2409: don't leak the file descriptor when doing ``open('some-dir')`` + * Windows fixes around vmprof + * Don't use ``sprintf()`` from inside a signal handler + * Test and fix bug from the ``guard_not_forced_2`` branch, which didn't + save the floating-point register + * ``_numpypy.add.reduce`` returns a scalar now + +* Performance improvements: + * Improve method calls on oldstyle classes + * Clean and refactor code for testing cpyext to allow sharing with py3.5 + * Refactor a building the map of reflected ops in ``_numpypy`` + * Improve merging of virtual states in the JIT in order to avoid jumping to the + preamble + * In JIT residual calls, if the called function starts with a fast-path like + ``if x.foo != 0: return x.foo``, then inline the check before doing the + ``CALL``. + * Ensure ``make_inputargs`` fails properly when given arguments with type + information + * Makes ``optimiseopt`` iterative instead of recursive so it can be reasoned + about more easily and debugging is faster + * Refactor and remove dead code from ``optimizeopt``, ``resume`` + + +.. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.6.0.html + +Please update, and continue to help us make PyPy better. + +Cheers diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py --- a/pypy/module/_cffi_backend/cbuffer.py +++ b/pypy/module/_cffi_backend/cbuffer.py @@ -3,6 +3,7 @@ from pypy.interpreter.gateway import unwrap_spec, interp2app from pypy.interpreter.typedef import TypeDef, make_weakref_descr from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypearray +from pypy.module._cffi_backend import ctypestruct from rpython.rlib.buffer import Buffer from rpython.rtyper.annlowlevel import llstr @@ -89,7 +90,12 @@ ctype = w_cdata.ctype if isinstance(ctype, ctypeptr.W_CTypePointer): if size < 0: - size = ctype.ctitem.size + structobj = w_cdata.get_structobj() + if (structobj is not None and + isinstance(structobj.ctype, ctypestruct.W_CTypeStructOrUnion)): + size = structobj._sizeof() + if size < 0: + size = ctype.ctitem.size elif isinstance(ctype, ctypearray.W_CTypeArray): if size < 0: size = w_cdata._sizeof() diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -329,7 +329,7 @@ def getattr(self, w_attr): cfield = self.getcfield(w_attr) with self as ptr: - w_res = cfield.read(ptr) + w_res = cfield.read(ptr, self) return w_res def setattr(self, w_attr, w_value): @@ -432,6 +432,9 @@ lst = ct.cdata_dir() return space.newlist([space.wrap(s) for s in lst]) + def get_structobj(self): + return None + class W_CDataMem(W_CData): """This is used only by the results of cffi.cast('int', x) @@ -453,28 +456,36 @@ by newp(). They create and free their own memory according to an allocator.""" - # the 'length' is either >= 0 for arrays, or -1 for pointers. - _attrs_ = ['length'] - _immutable_fields_ = ['length'] + # the 'allocated_length' is >= 0 for arrays; for var-sized + # structures it is the total size in bytes; otherwise it is -1. + _attrs_ = ['allocated_length'] + _immutable_fields_ = ['allocated_length'] def __init__(self, space, cdata, ctype, length=-1): W_CData.__init__(self, space, cdata, ctype) - self.length = length + self.allocated_length = length def _repr_extra(self): return self._repr_extra_owning() def _sizeof(self): ctype = self.ctype - if self.length >= 0: + if self.allocated_length >= 0: from pypy.module._cffi_backend import ctypearray - assert isinstance(ctype, ctypearray.W_CTypeArray) - return self.length * ctype.ctitem.size + if isinstance(ctype, ctypearray.W_CTypeArray): + return self.allocated_length * ctype.ctitem.size + else: + return self.allocated_length # var-sized struct size else: return ctype.size def get_array_length(self): - return self.length + from pypy.module._cffi_backend import ctypearray + assert isinstance(self.ctype, ctypearray.W_CTypeArray) + return self.allocated_length + + def get_structobj(self): + return self class W_CDataNewStd(W_CDataNewOwning): @@ -508,12 +519,19 @@ self.structobj = structobj def _repr_extra(self): - return self._repr_extra_owning() + return self.structobj._repr_extra_owning() def _do_getitem(self, ctype, i): assert i == 0 return self.structobj + def get_structobj(self): + structobj = self.structobj + if isinstance(structobj, W_CDataNewOwning): + return structobj + else: + return None + class W_CDataSliced(W_CData): """Subclass with an explicit length, for slices.""" diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -213,13 +213,16 @@ # a W_CDataPtrToStruct object which has a strong reference # to a W_CDataNewOwning that really contains the structure. # - if not space.is_w(w_init, space.w_None): - ctitem.force_lazy_struct() - if ctitem._with_var_array: + varsize_length = -1 + ctitem.force_lazy_struct() + if ctitem._with_var_array: + if not space.is_w(w_init, space.w_None): datasize = ctitem.convert_struct_from_object( lltype.nullptr(rffi.CCHARP.TO), w_init, datasize) + varsize_length = datasize # - cdatastruct = allocator.allocate(space, datasize, ctitem) + cdatastruct = allocator.allocate(space, datasize, ctitem, + length=varsize_length) ptr = cdatastruct.unsafe_escaping_ptr() cdata = cdataobj.W_CDataPtrToStructOrUnion(space, ptr, self, cdatastruct) diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -210,7 +210,7 @@ return W_CField(self.ctype, offset + self.offset, self.bitshift, self.bitsize, self.flags | fflags) - def read(self, cdata): + def read(self, cdata, w_cdata): cdata = rffi.ptradd(cdata, self.offset) if self.bitshift == self.BS_REGULAR: return self.ctype.convert_to_object(cdata) @@ -218,6 +218,14 @@ from pypy.module._cffi_backend import ctypearray ctype = self.ctype assert isinstance(ctype, ctypearray.W_CTypeArray) + structobj = w_cdata.get_structobj() + if structobj is not None: + # variable-length array + size = structobj.allocated_length - self.offset + if size >= 0: + arraylen = size // ctype.ctitem.size + return cdataobj.W_CDataSliced(ctype.space, cdata, ctype, + arraylen) return cdataobj.W_CData(ctype.space, cdata, ctype.ctptr) else: return self.convert_bitfield_to_object(cdata) diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py --- a/pypy/module/_cffi_backend/newtype.py +++ b/pypy/module/_cffi_backend/newtype.py @@ -353,7 +353,7 @@ if fbitsize < 0: # not a bitfield: common case - if isinstance(ftype, ctypearray.W_CTypeArray) and ftype.length==0: + if isinstance(ftype, ctypearray.W_CTypeArray) and ftype.length<=0: bs_flag = ctypestruct.W_CField.BS_EMPTY_ARRAY else: bs_flag = ctypestruct.W_CField.BS_REGULAR diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -3161,17 +3161,19 @@ assert d[1][0] == 'y' assert d[1][1].type is BArray assert d[1][1].offset == size_of_int() - assert d[1][1].bitshift == -1 + assert d[1][1].bitshift == -2 assert d[1][1].bitsize == -1 # p = newp(new_pointer_type(BStruct)) p.x = 42 assert p.x == 42 - assert typeof(p.y) is BIntP + assert typeof(p.y) is BArray + assert len(p.y) == 0 assert p.y == cast(BIntP, p) + 1 # p = newp(new_pointer_type(BStruct), [100]) assert p.x == 100 + assert len(p.y) == 0 # # Tests for # ffi.new("struct_with_var_array *", [field.., [the_array_items..]]) @@ -3186,6 +3188,10 @@ p.y[0] = 200 assert p.y[2] == 0 p.y[2] = 400 + assert len(p.y) == 3 + assert len(p[0].y) == 3 + assert len(buffer(p)) == sizeof(BInt) * 4 + assert sizeof(p[0]) == sizeof(BInt) * 4 plist.append(p) for i in range(20): p = plist[i] @@ -3193,13 +3199,31 @@ assert p.y[0] == 200 assert p.y[1] == i assert p.y[2] == 400 - assert list(p.y[0:3]) == [200, i, 400] + assert list(p.y) == [200, i, 400] # # the following assignment works, as it normally would, for any array field - p.y = [500, 600] - assert list(p.y[0:3]) == [500, 600, 400] + p.y = [501, 601] + assert list(p.y) == [501, 601, 400] + p[0].y = [500, 600] + assert list(p[0].y) == [500, 600, 400] + assert repr(p) == "<cdata 'foo *' owning %d bytes>" % ( + sizeof(BStruct) + 3 * sizeof(BInt),) + assert repr(p[0]) == "<cdata 'foo' owning %d bytes>" % ( + sizeof(BStruct) + 3 * sizeof(BInt),) + assert sizeof(p[0]) == sizeof(BStruct) + 3 * sizeof(BInt) + # + # from a non-owning pointer, we can't get the length + q = cast(new_pointer_type(BStruct), p) + assert q.y[0] == 500 + assert q[0].y[0] == 500 + py.test.raises(TypeError, len, q.y) + py.test.raises(TypeError, len, q[0].y) + assert typeof(q.y) is BIntP + assert typeof(q[0].y) is BIntP + assert sizeof(q[0]) == sizeof(BStruct) # # error cases + py.test.raises(IndexError, "p.y[4]") py.test.raises(TypeError, "p.y = cast(BIntP, 0)") py.test.raises(TypeError, "p.y = 15") py.test.raises(TypeError, "p.y = None") @@ -3264,6 +3288,33 @@ assert p.x[5] == 60 assert p.x[6] == 70 +def test_struct_array_not_aligned(): + # struct a { int x; char y; char z[]; }; + # ends up of size 8, but 'z' is at offset 5 + BChar = new_primitive_type("char") + BInt = new_primitive_type("int") + BCharP = new_pointer_type(BChar) + BArray = new_array_type(BCharP, None) + BStruct = new_struct_type("foo") + complete_struct_or_union(BStruct, [('x', BInt), + ('y', BChar), + ('z', BArray)]) + assert sizeof(BStruct) == 2 * size_of_int() + def offsetof(BType, fieldname): + return typeoffsetof(BType, fieldname)[1] + base = offsetof(BStruct, 'z') + assert base == size_of_int() + 1 + # + p = newp(new_pointer_type(BStruct), {'z': 3}) + assert sizeof(p[0]) == base + 3 + q = newp(new_pointer_type(BStruct), {'z': size_of_int()}) + assert sizeof(q) == size_of_ptr() + assert sizeof(q[0]) == base + size_of_int() + assert len(p.z) == 3 + assert len(p[0].z) == 3 + assert len(q.z) == size_of_int() + assert len(q[0].z) == size_of_int() + def test_ass_slice(): BChar = new_primitive_type("char") BArray = new_array_type(new_pointer_type(BChar), None) diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py --- a/pypy/module/_cffi_backend/test/test_recompiler.py +++ b/pypy/module/_cffi_backend/test/test_recompiler.py @@ -408,11 +408,14 @@ 'test_misdeclared_field_1', "struct foo_s { int a[6]; };") assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code - p = ffi.new("struct foo_s *") - # lazily build the fields and boom: - e = raises(ffi.error, getattr, p, "a") - assert str(e.value).startswith("struct foo_s: wrong size for field 'a' " - "(cdef says 20, but C compiler says 24)") + try: + # lazily build the fields and boom: + p = ffi.new("struct foo_s *") + p.a + assert False, "should have raised" + except ffi.error as e: + assert str(e).startswith("struct foo_s: wrong size for field 'a' " + "(cdef says 20, but C compiler says 24)") def test_open_array_in_struct(self): ffi, lib = self.prepare( @@ -420,8 +423,10 @@ 'test_open_array_in_struct', "struct foo_s { int b; int a[]; };") assert ffi.sizeof("struct foo_s") == 4 - p = ffi.new("struct foo_s *", [5, [10, 20, 30]]) + p = ffi.new("struct foo_s *", [5, [10, 20, 30, 40]]) assert p.a[2] == 30 + assert ffi.sizeof(p) == ffi.sizeof("void *") + assert ffi.sizeof(p[0]) == 5 * ffi.sizeof("int") def test_math_sin_type(self): ffi, lib = self.prepare( @@ -954,6 +959,7 @@ "struct foo_s { int x; int a[5][8]; int y; };") assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int') s = ffi.new("struct foo_s *") + assert ffi.typeof(s.a) == ffi.typeof("int[5][8]") assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int') assert s.a[4][7] == 0 raises(IndexError, 's.a[4][8]') @@ -961,6 +967,18 @@ assert ffi.typeof(s.a) == ffi.typeof("int[5][8]") assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]") + def test_struct_array_guess_length_3(self): + ffi, lib = self.prepare( + "struct foo_s { int a[][...]; };", + 'test_struct_array_guess_length_3', + "struct foo_s { int x; int a[5][7]; int y; };") + assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int') + s = ffi.new("struct foo_s *") + assert ffi.typeof(s.a) == ffi.typeof("int[][7]") + assert s.a[4][6] == 0 + raises(IndexError, 's.a[4][7]') + assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]") + def test_global_var_array_2(self): ffi, lib = self.prepare( "int a[...][...];", diff --git a/pypy/module/cpyext/test/test_ztranslation.py b/pypy/module/cpyext/test/test_ztranslation.py deleted file mode 100644 --- a/pypy/module/cpyext/test/test_ztranslation.py +++ /dev/null @@ -1,10 +0,0 @@ -from pypy.objspace.fake.checkmodule import checkmodule -from pypy.module.cpyext import pyobject - -def test_cpyext_translates(monkeypatch): - def from_ref(space, ref): - # XXX: avoid 'assert isinstance(w_type, W_TypeObject)' from the - # original from_ref, just return w_some_obj - return space.w_object - monkeypatch.setattr(pyobject, 'from_ref', from_ref) - checkmodule('cpyext', '_rawffi', translate_startup=False) 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 @@ -273,7 +273,7 @@ if len(slot_names) == 1: if not getattr(pto, slot_names[0]): setattr(pto, slot_names[0], slot_func_helper) - elif (w_type.getname(space) in ('list', 'tuple') and + 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 # names like __mul__ map to more than one slot, and we have no diff --git a/pypy/module/micronumpy/test/test_ztranslation.py b/pypy/module/micronumpy/test/test_ztranslation.py deleted file mode 100644 --- a/pypy/module/micronumpy/test/test_ztranslation.py +++ /dev/null @@ -1,4 +0,0 @@ -from pypy.objspace.fake.checkmodule import checkmodule - -def test_numpy_translates(): - checkmodule('micronumpy') diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py @@ -1356,15 +1356,15 @@ assert ffi.getctype("e1*") == 'e1 *' def test_opaque_enum(self): + import warnings ffi = FFI(backend=self.Backend()) ffi.cdef("enum foo;") - from cffi import __version_info__ - if __version_info__ < (1, 8): - py.test.skip("re-enable me in version 1.8") - e = py.test.raises(CDefError, ffi.cast, "enum foo", -1) - assert str(e.value) == ( - "'enum foo' has no values explicitly defined: refusing to guess " - "which integer type it is meant to be (unsigned/signed, int/long)") + with warnings.catch_warnings(record=True) as log: + n = ffi.cast("enum foo", -1) + assert int(n) == 0xffffffff + assert str(log[0].message) == ( + "'enum foo' has no values explicitly defined; " + "guessing that it is equivalent to 'unsigned int'") def test_new_ctype(self): ffi = FFI(backend=self.Backend()) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py @@ -283,10 +283,20 @@ ffi.cdef("struct foo_s { int x; int a[]; };") p = ffi.new("struct foo_s *", [100, [200, 300, 400]]) assert p.x == 100 - assert ffi.typeof(p.a) is ffi.typeof("int *") # no length available + assert ffi.typeof(p.a) is ffi.typeof("int[]") + assert len(p.a) == 3 # length recorded assert p.a[0] == 200 assert p.a[1] == 300 assert p.a[2] == 400 + assert list(p.a) == [200, 300, 400] + q = ffi.cast("struct foo_s *", p) + assert q.x == 100 + assert ffi.typeof(q.a) is ffi.typeof("int *") # no length recorded + py.test.raises(TypeError, len, q.a) + assert q.a[0] == 200 + assert q.a[1] == 300 + assert q.a[2] == 400 + py.test.raises(TypeError, list, q.a) @pytest.mark.skipif("sys.platform != 'win32'") def test_getwinerror(self): diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py @@ -562,7 +562,8 @@ "int bar(struct foo_s *f) { return f->a[14]; }\n") assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') s = ffi.new("struct foo_s *") - assert ffi.typeof(s.a) is ffi.typeof('int *') # because no length + assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length + assert len(s.a) == 18 # max length, computed from the size and start offset s.a[14] = 4242 assert lib.bar(s) == 4242 # with no declared length, out-of-bound accesses are not detected @@ -592,10 +593,15 @@ ffi.verify("struct foo_s { int x; int a[]; };") assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int') s = ffi.new("struct foo_s *", [424242, 4]) - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') # the same in C + assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int') + # ^^^ explanation: if you write in C: "char x[5];", then + # "sizeof(x)" will evaluate to 5. The behavior above is + # a generalization of that to "struct foo_s[len(a)=5] x;" + # if you could do that in C. assert s.a[3] == 0 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int') assert s.a[3] == -10 s = ffi.new("struct foo_s *") assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') @@ -610,10 +616,10 @@ ffi.verify("struct foo_s { int x, y; int a[]; };") assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int') s = ffi.new("struct foo_s *", [424242, 4]) - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int') assert s.a[3] == 0 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int') assert s.a[3] == -10 s = ffi.new("struct foo_s *") assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py @@ -1634,10 +1634,19 @@ # struct array_no_length { int x; int a[]; }; p = ffi.new("struct array_no_length *", [100, [200, 300, 400]]) assert p.x == 100 - assert ffi.typeof(p.a) is ffi.typeof("int *") # no length available + assert ffi.typeof(p.a) is ffi.typeof("int[]") # length available assert p.a[0] == 200 assert p.a[1] == 300 assert p.a[2] == 400 + assert len(p.a) == 3 + assert list(p.a) == [200, 300, 400] + q = ffi.cast("struct array_no_length *", p) + assert ffi.typeof(q.a) is ffi.typeof("int *") # no length available + assert q.a[0] == 200 + assert q.a[1] == 300 + assert q.a[2] == 400 + py.test.raises(TypeError, len, q.a) + py.test.raises(TypeError, list, q.a) def test_from_buffer(self): import array diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py @@ -400,11 +400,14 @@ pass # ok, fail during compilation already (e.g. C++) else: assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code - p = ffi.new("struct foo_s *") - # lazily build the fields and boom: - e = py.test.raises(ffi.error, "p.a") - assert str(e.value).startswith("struct foo_s: wrong size for field 'a' " - "(cdef says 20, but C compiler says 24)") + try: + # lazily build the fields and boom: + p = ffi.new("struct foo_s *") + p.a + assert False, "should have raised" + except ffi.error as e: + assert str(e).startswith("struct foo_s: wrong size for field 'a' " + "(cdef says 20, but C compiler says 24)") def test_open_array_in_struct(): ffi = FFI() @@ -412,8 +415,10 @@ verify(ffi, 'test_open_array_in_struct', "struct foo_s { int b; int a[]; };") assert ffi.sizeof("struct foo_s") == 4 - p = ffi.new("struct foo_s *", [5, [10, 20, 30]]) + p = ffi.new("struct foo_s *", [5, [10, 20, 30, 40]]) assert p.a[2] == 30 + assert ffi.sizeof(p) == ffi.sizeof("void *") + assert ffi.sizeof(p[0]) == 5 * ffi.sizeof("int") def test_math_sin_type(): ffi = FFI() @@ -999,6 +1004,7 @@ "struct foo_s { int x; int a[5][8]; int y; };") assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int') s = ffi.new("struct foo_s *") + assert ffi.typeof(s.a) == ffi.typeof("int[5][8]") assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int') assert s.a[4][7] == 0 py.test.raises(IndexError, 's.a[4][8]') @@ -1013,7 +1019,7 @@ "struct foo_s { int x; int a[5][7]; int y; };") assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int') s = ffi.new("struct foo_s *") - assert ffi.typeof(s.a) == ffi.typeof("int(*)[7]") + assert ffi.typeof(s.a) == ffi.typeof("int[][7]") assert s.a[4][6] == 0 py.test.raises(IndexError, 's.a[4][7]') assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]") diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py @@ -547,7 +547,8 @@ "int bar(struct foo_s *f) { return f->a[14]; }\n") assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') s = ffi.new("struct foo_s *") - assert ffi.typeof(s.a) is ffi.typeof('int *') # because no length + assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length + assert len(s.a) == 18 # max length, computed from the size and start offset s.a[14] = 4242 assert lib.bar(s) == 4242 # with no declared length, out-of-bound accesses are not detected @@ -577,10 +578,15 @@ ffi.verify("struct foo_s { int x; int a[]; };") assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int') s = ffi.new("struct foo_s *", [424242, 4]) - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') # the same in C + assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int') + # ^^^ explanation: if you write in C: "char x[5];", then + # "sizeof(x)" will evaluate to 5. The behavior above is + # a generalization of that to "struct foo_s[len(a)=5] x;" + # if you could do that in C. assert s.a[3] == 0 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int') assert s.a[3] == -10 s = ffi.new("struct foo_s *") assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') @@ -595,10 +601,10 @@ ffi.verify("struct foo_s { int x, y; int a[]; };") assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int') s = ffi.new("struct foo_s *", [424242, 4]) - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int') assert s.a[3] == 0 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') + assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int') assert s.a[3] == -10 s = ffi.new("struct foo_s *") assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2662,7 +2662,8 @@ """, namespace=locals()) looptoken = JitCellToken() self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) - deadframe = self.cpu.execute_token(looptoken, 20.25) + x = longlong.getfloatstorage(20.25) + deadframe = self.cpu.execute_token(looptoken, x) fail = self.cpu.get_latest_descr(deadframe) assert fail.identifier == 0 frame = self.cpu.get_ref_value(deadframe, 0) @@ -2671,7 +2672,8 @@ if not getattr(self.cpu, 'is_llgraph', False): assert frame == deadframe deadframe2 = self.cpu.force(frame) - assert self.cpu.get_float_value(deadframe2, 0) == 22.75 + x = self.cpu.get_float_value(deadframe2, 0) + assert longlong.getrealfloat(x) == 22.75 def test_call_to_c_function(self): from rpython.rlib.libffi import CDLL, types, ArgChain, FUNCFLAG_CDECL _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit