Author: Armin Rigo <[email protected]>
Branch:
Changeset: r95043:feb6754915bc
Date: 2018-08-30 12:26 +0200
http://bitbucket.org/pypy/pypy/changeset/feb6754915bc/
Log: update to cffi/1443130c25e1
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -8,20 +8,43 @@
the same works for the other two macros. Py_DEBUG implies them,
but not the other way around.
- Issue #350 is still open: on Windows, the code here causes it to link
- with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was
- attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv
- does not make PYTHON3.DLL available, and so the "correctly" compiled
- version would not run inside a virtualenv. We will re-apply the fix
- after virtualenv has been fixed for some time. For explanation, see
- issue #355. For a workaround if you want PYTHON3.DLL and don't worry
- about virtualenv, see issue #350. See also 'py_limited_api' in
- setuptools_ext.py.
+ The implementation is messy (issue #350): on Windows, with _MSC_VER,
+ we have to define Py_LIMITED_API even before including pyconfig.h.
+ In that case, we guess what pyconfig.h will do to the macros above,
+ and check our guess after the #include.
+
+ Note that on Windows, with CPython 3.x, you need virtualenv version
+ >= 16.0.0. Older versions don't copy PYTHON3.DLL. As a workaround
+ you can remove the definition of Py_LIMITED_API here.
+
+ See also 'py_limited_api' in cffi/setuptools_ext.py.
*/
#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API)
-# include <pyconfig.h>
-# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
-# define Py_LIMITED_API
+# ifdef _MSC_VER
+# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) &&
!defined(Py_REF_DEBUG)
+# define Py_LIMITED_API
+# endif
+# include <pyconfig.h>
+ /* sanity-check: Py_LIMITED_API will cause crashes if any of these
+ are also defined. Normally, the Python file PC/pyconfig.h does not
+ cause any of these to be defined, with the exception that _DEBUG
+ causes Py_DEBUG. Double-check that. */
+# ifdef Py_LIMITED_API
+# if defined(Py_DEBUG)
+# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API
is set"
+# endif
+# if defined(Py_TRACE_REFS)
+# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but
Py_LIMITED_API is set"
+# endif
+# if defined(Py_REF_DEBUG)
+# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but
Py_LIMITED_API is set"
+# endif
+# endif
+# else
+# include <pyconfig.h>
+# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
+# define Py_LIMITED_API
+# endif
# endif
#endif
diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py
--- a/lib_pypy/cffi/backend_ctypes.py
+++ b/lib_pypy/cffi/backend_ctypes.py
@@ -636,6 +636,10 @@
if isinstance(init, bytes):
init = [init[i:i+1] for i in range(len(init))]
else:
+ if isinstance(init, CTypesGenericArray):
+ if (len(init) != len(blob) or
+ not isinstance(init, CTypesArray)):
+ raise TypeError("length/type mismatch: %s" %
(init,))
init = tuple(init)
if len(init) > len(blob):
raise IndexError("too many initializers")
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
@@ -81,13 +81,8 @@
it doesn't so far, creating troubles. That's why we check
for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent
of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401)
-
- On Windows, it's better not to use py_limited_api until issue #355
- can be resolved (by having virtualenv copy PYTHON3.DLL). See also
- the start of _cffi_include.h.
"""
- if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount')
- and sys.platform != 'win32'):
+ if 'py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount'):
import setuptools
try:
setuptools_major_version =
int(setuptools.__version__.partition('.')[0])
diff --git a/pypy/module/_cffi_backend/ctypeobj.py
b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -105,6 +105,11 @@
# ctype 'A' must be a pointer to same type, not cdata
# 'B'", but with A=B, then give instead a different error
# message to try to clear up the confusion
+ if self is w_got.ctype:
+ raise oefmt(space.w_SystemError,
+ "initializer for ctype '%s' is correct, but we get "
+ "an internal mismatch--please report a bug",
+ self.name)
return oefmt(space.w_TypeError,
"initializer for ctype '%s' appears indeed to "
"be '%s', but the types are different (check "
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
@@ -75,7 +75,8 @@
self._convert_array_from_listview(cdata, space.listview(w_ob))
elif self.accept_str:
if not space.isinstance_w(w_ob, space.w_bytes):
- raise self._convert_error("str or list or tuple", w_ob)
+ return self._convert_array_from_cdataobj(cdata, w_ob,
+ "str or list or tuple")
s = space.bytes_w(w_ob)
n = len(s)
if self.length >= 0 and n > self.length:
@@ -90,7 +91,8 @@
elif isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar):
from pypy.module._cffi_backend import wchar_helper
if not space.isinstance_w(w_ob, space.w_unicode):
- raise self._convert_error("unicode or list or tuple", w_ob)
+ return self._convert_array_from_cdataobj(cdata, w_ob,
+ "unicode or list or tuple")
s = space.unicode_w(w_ob)
if self.ctitem.size == 2:
n = wchar_helper.unicode_size_as_char16(s)
@@ -111,7 +113,19 @@
else:
wchar_helper.unicode_to_char32(s, cdata, n, add_final_zero)
else:
- raise self._convert_error("list or tuple", w_ob)
+ return self._convert_array_from_cdataobj(cdata, w_ob,
+ "list or tuple")
+
+ def _convert_array_from_cdataobj(self, cdata, w_ob, errmsg):
+ if isinstance(w_ob, cdataobj.W_CData) and w_ob.ctype is self:
+ length = w_ob.get_array_length()
+ with w_ob as source:
+ source = rffi.cast(rffi.VOIDP, source)
+ target = rffi.cast(rffi.VOIDP, cdata)
+ size = rffi.cast(rffi.SIZE_T, self.ctitem.size * length)
+ rffi.c_memcpy(target, source, size)
+ else:
+ raise self._convert_error(errmsg, w_ob)
def _must_be_string_of_zero_or_one(self, s):
for c in s:
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
@@ -1862,7 +1862,7 @@
def test_newp_copying():
"""Test that we can do newp(<type>, <cdata of the given type>) for most
- types, with the exception of arrays, like in C.
+ types, including same-type arrays.
"""
BInt = new_primitive_type("int")
p = newp(new_pointer_type(BInt), cast(BInt, 42))
@@ -1891,8 +1891,9 @@
a1 = newp(BArray, [1, 2, 3, 4])
py.test.raises(TypeError, newp, BArray, a1)
BArray6 = new_array_type(new_pointer_type(BInt), 6)
- a1 = newp(BArray6, None)
- py.test.raises(TypeError, newp, BArray6, a1)
+ a1 = newp(BArray6, [10, 20, 30])
+ a2 = newp(BArray6, a1)
+ assert list(a2) == [10, 20, 30, 0, 0, 0]
#
s1 = newp(BStructPtr, [42])
s2 = newp(BStructPtr, s1[0])
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -563,3 +563,13 @@
assert len(z) == 2
assert ffi.cast("int *", z)[0] == 0x12345
assert list(z) == [u'\U00012345', u'\x00'] # maybe a 2-unichars str
+
+ def test_ffi_array_as_init(self):
+ import _cffi_backend as _cffi1_backend
+ ffi = _cffi1_backend.FFI()
+ p = ffi.new("int[4]", [10, 20, 30, 400])
+ q = ffi.new("int[4]", p)
+ assert list(q) == [10, 20, 30, 400]
+ raises(TypeError, ffi.new, "int[3]", p)
+ raises(TypeError, ffi.new, "int[5]", p)
+ raises(TypeError, ffi.new, "int16_t[4]", p)
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
@@ -1973,3 +1973,18 @@
assert seen[1] == 101
assert seen[2] == 202
assert seen[3] == 303
+
+ def test_ffi_array_as_init(self):
+ ffi = FFI(backend=self.Backend())
+ p = ffi.new("int[4]", [10, 20, 30, 400])
+ q = ffi.new("int[4]", p)
+ assert list(q) == [10, 20, 30, 400]
+ py.test.raises(TypeError, ffi.new, "int[3]", p)
+ py.test.raises(TypeError, ffi.new, "int[5]", p)
+ py.test.raises(TypeError, ffi.new, "int16_t[4]", p)
+ s = ffi.new("struct {int i[4];}*", {'i': p})
+ assert list(s.i) == [10, 20, 30, 400]
+
+ def test_too_many_initializers(self):
+ ffi = FFI(backend=self.Backend())
+ py.test.raises(IndexError, ffi.new, "int[4]", [10, 20, 30, 40, 50])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit