[pypy-commit] pypy default: Update to cffi/9ba268ca7739. In-progress.
arigo
noreply at buildbot.pypy.org
Sat Nov 9 10:34:44 CET 2013
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r67887:d2503dcb595a
Date: 2013-11-09 09:34 +0100
http://bitbucket.org/pypy/pypy/changeset/d2503dcb595a/
Log: Update to cffi/9ba268ca7739. In-progress.
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
@@ -245,19 +245,22 @@
space = self.space
if isinstance(w_other, W_CData):
from pypy.module._cffi_backend import ctypeptr, ctypearray
+ from pypy.module._cffi_backend import ctypevoid
ct = w_other.ctype
if isinstance(ct, ctypearray.W_CTypeArray):
ct = ct.ctptr
#
if (ct is not self.ctype or
not isinstance(ct, ctypeptr.W_CTypePointer) or
- ct.ctitem.size <= 0):
+ (ct.ctitem.size <= 0 and not ct.is_void_ptr)):
raise operationerrfmt(space.w_TypeError,
"cannot subtract cdata '%s' and cdata '%s'",
self.ctype.name, ct.name)
#
+ itemsize = ct.ctitem.size
+ if itemsize <= 0: itemsize = 1
diff = (rffi.cast(lltype.Signed, self._cdata) -
- rffi.cast(lltype.Signed, w_other._cdata)) // ct.ctitem.size
+ rffi.cast(lltype.Signed, w_other._cdata)) // itemsize
return space.wrap(diff)
#
return self._add_or_sub(w_other, -1)
@@ -441,6 +444,7 @@
__getitem__ = interp2app(W_CData.getitem),
__setitem__ = interp2app(W_CData.setitem),
__add__ = interp2app(W_CData.add),
+ __radd__ = interp2app(W_CData.add),
__sub__ = interp2app(W_CData.sub),
__getattr__ = interp2app(W_CData.getattr),
__setattr__ = interp2app(W_CData.setattr),
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
@@ -236,11 +236,15 @@
def add(self, cdata, i):
space = self.space
ctitem = self.ctitem
+ itemsize = ctitem.size
if ctitem.size < 0:
- raise operationerrfmt(space.w_TypeError,
+ if self.is_void_ptr:
+ itemsize = 1
+ else:
+ raise operationerrfmt(space.w_TypeError,
"ctype '%s' points to items of unknown size",
self.name)
- p = rffi.ptradd(cdata, i * self.ctitem.size)
+ p = rffi.ptradd(cdata, i * itemsize)
return cdataobj.W_CData(space, p, self)
def cast(self, w_ob):
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
@@ -542,6 +542,7 @@
assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % (
3*5*size_of_int(),)
assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x")
+ assert 0 + a == a + 0 != 1 + a == a + 1
assert repr(a[0]).startswith("<cdata 'int[5]' 0x")
assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x")
assert repr(a[0] + 0).startswith("<cdata 'int *' 0x")
@@ -1631,9 +1632,6 @@
def test_void_errors():
py.test.raises(ValueError, alignof, new_void_type())
py.test.raises(TypeError, newp, new_pointer_type(new_void_type()), None)
- x = cast(new_pointer_type(new_void_type()), 42)
- py.test.raises(TypeError, "x + 1")
- py.test.raises(TypeError, "x - 1")
def test_too_many_items():
BChar = new_primitive_type("char")
@@ -2952,6 +2950,166 @@
_test_bitfield_details(flag=4)
+def test_struct_array_no_length():
+ BInt = new_primitive_type("int")
+ BIntP = new_pointer_type(BInt)
+ BArray = new_array_type(BIntP, None)
+ BStruct = new_struct_type("foo")
+ py.test.raises(TypeError, complete_struct_or_union,
+ BStruct, [('x', BArray),
+ ('y', BInt)])
+ #
+ BStruct = new_struct_type("foo")
+ complete_struct_or_union(BStruct, [('x', BInt),
+ ('y', BArray)])
+ assert sizeof(BStruct) == size_of_int()
+ d = BStruct.fields
+ assert len(d) == 2
+ assert d[0][0] == 'x'
+ assert d[0][1].type is BInt
+ assert d[0][1].offset == 0
+ assert d[0][1].bitshift == -1
+ assert d[0][1].bitsize == -1
+ 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].bitsize == -1
+ #
+ p = newp(new_pointer_type(BStruct))
+ p.x = 42
+ assert p.x == 42
+ assert typeof(p.y) is BIntP
+ assert p.y == cast(BIntP, p) + 1
+ #
+ p = newp(new_pointer_type(BStruct), [100])
+ assert p.x == 100
+ #
+ # Tests for
+ # ffi.new("struct_with_var_array *", [field.., [the_array_items..]])
+ # ffi.new("struct_with_var_array *", [field.., array_size])
+ plist = []
+ for i in range(20):
+ if i % 2 == 0:
+ p = newp(new_pointer_type(BStruct), [100, [200, i, 400]])
+ else:
+ p = newp(new_pointer_type(BStruct), [100, 3])
+ p.y[1] = i
+ p.y[0] = 200
+ assert p.y[2] == 0
+ p.y[2] = 400
+ plist.append(p)
+ for i in range(20):
+ p = plist[i]
+ assert p.x == 100
+ assert p.y[0] == 200
+ assert p.y[1] == i
+ assert p.y[2] == 400
+ assert list(p.y[0:3]) == [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]
+ #
+ # error cases
+ py.test.raises(TypeError, "p.y = cast(BIntP, 0)")
+ py.test.raises(TypeError, "p.y = 15")
+ py.test.raises(TypeError, "p.y = None")
+ #
+ # accepting this may be specified by the C99 standard,
+ # or a GCC strangeness...
+ BStruct2 = new_struct_type("bar")
+ complete_struct_or_union(BStruct2, [('f', BStruct),
+ ('n', BInt)])
+ p = newp(new_pointer_type(BStruct2), {'n': 42})
+ assert p.n == 42
+ #
+ # more error cases
+ py.test.raises(TypeError, newp, new_pointer_type(BStruct), [100, None])
+ BArray4 = new_array_type(BIntP, 4)
+ BStruct4 = new_struct_type("test4")
+ complete_struct_or_union(BStruct4, [('a', BArray4)]) # not varsized
+ py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [None])
+ py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [4])
+ p = newp(new_pointer_type(BStruct4), [[10, 20, 30]])
+ assert p.a[0] == 10
+ assert p.a[1] == 20
+ assert p.a[2] == 30
+ assert p.a[3] == 0
+
+def test_struct_array_no_length_explicit_position():
+ BInt = new_primitive_type("int")
+ BIntP = new_pointer_type(BInt)
+ BArray = new_array_type(BIntP, None)
+ BStruct = new_struct_type("foo")
+ complete_struct_or_union(BStruct, [('x', BArray, -1, 0), # actually 3 items
+ ('y', BInt, -1, 12)])
+ p = newp(new_pointer_type(BStruct), [[10, 20], 30])
+ assert p.x[0] == 10
+ assert p.x[1] == 20
+ assert p.x[2] == 0
+ assert p.y == 30
+ p = newp(new_pointer_type(BStruct), {'x': [40], 'y': 50})
+ assert p.x[0] == 40
+ assert p.x[1] == 0
+ assert p.x[2] == 0
+ assert p.y == 50
+ p = newp(new_pointer_type(BStruct), {'y': 60})
+ assert p.x[0] == 0
+ assert p.x[1] == 0
+ assert p.x[2] == 0
+ assert p.y == 60
+ #
+ # This "should" work too, allocating a larger structure
+ # (a bit strange in this case, but useful in general)
+ plist = []
+ for i in range(20):
+ p = newp(new_pointer_type(BStruct), [[10, 20, 30, 40, 50, 60, 70]])
+ plist.append(p)
+ for i in range(20):
+ p = plist[i]
+ assert p.x[0] == 10
+ assert p.x[1] == 20
+ assert p.x[2] == 30
+ assert p.x[3] == 40 == p.y
+ assert p.x[4] == 50
+ assert p.x[5] == 60
+ assert p.x[6] == 70
+
+def test_ass_slice():
+ BChar = new_primitive_type("char")
+ BArray = new_array_type(new_pointer_type(BChar), None)
+ p = newp(BArray, b"foobar")
+ p[2:5] = [b"*", b"Z", b"T"]
+ p[1:3] = b"XY"
+ assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"]
+ py.test.raises(TypeError, "p[1:5] = u+'XYZT'")
+ py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
+ #
+ BUniChar = new_primitive_type("wchar_t")
+ BArray = new_array_type(new_pointer_type(BUniChar), None)
+ p = newp(BArray, u+"foobar")
+ p[2:5] = [u+"*", u+"Z", u+"T"]
+ p[1:3] = u+"XY"
+ assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"]
+ py.test.raises(TypeError, "p[1:5] = b'XYZT'")
+ py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]")
+
+def test_void_p_arithmetic():
+ BVoid = new_void_type()
+ BInt = new_primitive_type("intptr_t")
+ p = cast(new_pointer_type(BVoid), 100000)
+ assert int(cast(BInt, p)) == 100000
+ assert int(cast(BInt, p + 42)) == 100042
+ assert int(cast(BInt, p - (-42))) == 100042
+ assert (p + 42) - p == 42
+ q = cast(new_pointer_type(new_primitive_type("char")), 100000)
+ py.test.raises(TypeError, "p - q")
+ py.test.raises(TypeError, "q - p")
+ py.test.raises(TypeError, "p + cast(new_primitive_type('int'), 42)")
+ py.test.raises(TypeError, "p - cast(new_primitive_type('int'), 42)")
+
+
def test_version():
# this test is here mostly for PyPy
assert __version__ == "0.7"
More information about the pypy-commit
mailing list