Author: Armin Rigo <[email protected]>
Branch:
Changeset: r89754:f6c083857478
Date: 2017-01-25 00:53 +0100
http://bitbucket.org/pypy/pypy/changeset/f6c083857478/
Log: update to cffi/ece6f0f2da93
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
@@ -323,17 +323,28 @@
#
return self._add_or_sub(w_other, -1)
- def getcfield(self, w_attr):
- return self.ctype.getcfield(self.space.str_w(w_attr))
+ def getcfield(self, w_attr, mode):
+ space = self.space
+ attr = space.str_w(w_attr)
+ try:
+ cfield = self.ctype.getcfield(attr)
+ except KeyError:
+ raise oefmt(space.w_AttributeError, "cdata '%s' has no field '%s'",
+ self.ctype.name, attr)
+ if cfield is None:
+ raise oefmt(space.w_AttributeError,
+ "cdata '%s' points to an opaque type: cannot %s
fields",
+ self.ctype.name, mode)
+ return cfield
def getattr(self, w_attr):
- cfield = self.getcfield(w_attr)
+ cfield = self.getcfield(w_attr, mode="read")
with self as ptr:
w_res = cfield.read(ptr, self)
return w_res
def setattr(self, w_attr, w_value):
- cfield = self.getcfield(w_attr)
+ cfield = self.getcfield(w_attr, mode="write")
with self as ptr:
cfield.write(ptr, w_value)
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
@@ -345,7 +345,10 @@
return result
def getcfield(self, attr):
- return self.ctitem.getcfield(attr)
+ from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion
+ if isinstance(self.ctitem, W_CTypeStructOrUnion):
+ return self.ctitem.getcfield(attr)
+ return W_CType.getcfield(self, attr)
def typeoffsetof_field(self, fieldname, following):
if following == 0:
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
@@ -161,18 +161,18 @@
return self._fields_dict[attr]
def getcfield(self, attr):
- ready = self._fields_dict is not None
- if not ready and self.size >= 0:
+ # Returns a W_CField. Error cases: returns None if we are an
+ # opaque struct; or raises KeyError if the particular field
+ # 'attr' does not exist. The point of not directly building the
+ # error here is to get the exact ctype in the error message: it
+ # might be of the kind 'struct foo' or 'struct foo *'.
+ if self._fields_dict is None:
+ if self.size < 0:
+ return None
self.force_lazy_struct()
- ready = True
- if ready:
- self = jit.promote(self)
- attr = jit.promote_string(attr)
- try:
- return self._getcfield_const(attr)
- except KeyError:
- pass
- return W_CType.getcfield(self, attr)
+ self = jit.promote(self)
+ attr = jit.promote_string(attr)
+ return self._getcfield_const(attr) # <= KeyError here
def cdata_dir(self):
if self.size < 0:
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
@@ -737,8 +737,14 @@
BInt = new_primitive_type("int")
BStruct = new_struct_type("struct foo")
BStructPtr = new_pointer_type(BStruct)
- p = cast(BStructPtr, 0)
- py.test.raises(AttributeError, "p.a1") # opaque
+ p = cast(BStructPtr, 42)
+ e = py.test.raises(AttributeError, "p.a1") # opaque
+ assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
+ "cannot read fields")
+ e = py.test.raises(AttributeError, "p.a1 = 10") # opaque
+ assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
+ "cannot write fields")
+
complete_struct_or_union(BStruct, [('a1', BInt, -1),
('a2', BInt, -1)])
p = newp(BStructPtr, None)
@@ -749,8 +755,29 @@
assert s.a2 == 123
py.test.raises(OverflowError, "s.a1 = sys.maxsize+1")
assert s.a1 == 0
- py.test.raises(AttributeError, "p.foobar")
- py.test.raises(AttributeError, "s.foobar")
+ e = py.test.raises(AttributeError, "p.foobar")
+ assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
+ e = py.test.raises(AttributeError, "p.foobar = 42")
+ assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
+ e = py.test.raises(AttributeError, "s.foobar")
+ assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
+ e = py.test.raises(AttributeError, "s.foobar = 42")
+ assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
+ j = cast(BInt, 42)
+ e = py.test.raises(AttributeError, "j.foobar")
+ assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
+ e = py.test.raises(AttributeError, "j.foobar = 42")
+ assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
+ j = cast(new_pointer_type(BInt), 42)
+ e = py.test.raises(AttributeError, "j.foobar")
+ assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
+ e = py.test.raises(AttributeError, "j.foobar = 42")
+ assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
+ pp = newp(new_pointer_type(BStructPtr), p)
+ e = py.test.raises(AttributeError, "pp.a1")
+ assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
+ e = py.test.raises(AttributeError, "pp.a1 = 42")
+ assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
def test_union_instance():
BInt = new_primitive_type("int")
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit