[pypy-commit] cffi default: Support dir(p), where p is a struct or pointer-to-struct, to obtain
arigo
pypy.commits at gmail.com
Mon Jun 6 12:00:20 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r2715:0a5f59abb0e0
Date: 2016-06-06 18:00 +0200
http://bitbucket.org/cffi/cffi/changeset/0a5f59abb0e0/
Log: Support dir(p), where p is a struct or pointer-to-struct, to obtain
the list of field names.
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -2703,6 +2703,27 @@
return res;
}
+static PyObject *cdata_dir(PyObject *cd, PyObject *noarg)
+{
+ CTypeDescrObject *ct = ((CDataObject *)cd)->c_type;
+
+ /* replace the type 'pointer-to-t' with just 't' */
+ if (ct->ct_flags & CT_POINTER) {
+ ct = ct->ct_itemdescr;
+ }
+ if ((ct->ct_flags & (CT_STRUCT | CT_UNION)) &&
+ !(ct->ct_flags & CT_IS_OPAQUE)) {
+
+ /* for non-opaque structs or unions */
+ if (force_lazy_struct(ct) < 0)
+ return NULL;
+ return PyDict_Keys(ct->ct_stuff);
+ }
+ else {
+ return PyList_New(0); /* empty list for the other cases */
+ }
+}
+
static PyObject *cdata_iter(CDataObject *);
static PyNumberMethods CData_as_number = {
@@ -2751,6 +2772,11 @@
(objobjargproc)cdata_ass_sub, /*mp_ass_subscript*/
};
+static PyMethodDef cdata_methods[] = {
+ {"__dir__", cdata_dir, METH_NOARGS},
+ {NULL, NULL} /* sentinel */
+};
+
static PyTypeObject CData_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_cffi_backend.CData",
@@ -2779,6 +2805,7 @@
offsetof(CDataObject, c_weakreflist), /* tp_weaklistoffset */
(getiterfunc)cdata_iter, /* tp_iter */
0, /* tp_iternext */
+ cdata_methods, /* tp_methods */
};
static PyTypeObject CDataOwning_Type = {
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -88,8 +88,8 @@
assert repr(p) == "<ctype 'signed char'>"
def check_dir(p, expected):
- got = set(name for name in dir(p) if not name.startswith('_'))
- assert got == set(expected)
+ got = [name for name in dir(p) if not name.startswith('_')]
+ assert got == sorted(expected)
def test_inspect_primitive_type():
p = new_primitive_type("signed char")
@@ -3619,3 +3619,23 @@
#
py.test.raises(ValueError, unpack, p0, -1)
py.test.raises(ValueError, unpack, p, -1)
+
+def test_cdata_dir():
+ BInt = new_primitive_type("int")
+ p = cast(BInt, 42)
+ check_dir(p, [])
+ p = newp(new_array_type(new_pointer_type(BInt), None), 5)
+ check_dir(p, [])
+ BStruct = new_struct_type("foo")
+ p = cast(new_pointer_type(BStruct), 0)
+ check_dir(p, []) # opaque
+ complete_struct_or_union(BStruct, [('a2', BInt, -1),
+ ('a1', BInt, -1)])
+ check_dir(p, ['a1', 'a2']) # always sorted
+ p = newp(new_pointer_type(BStruct), None)
+ check_dir(p, ['a1', 'a2'])
+ check_dir(p[0], ['a1', 'a2'])
+ pp = newp(new_pointer_type(new_pointer_type(BStruct)), p)
+ check_dir(pp, [])
+ check_dir(pp[0], ['a1', 'a2'])
+ check_dir(pp[0][0], ['a1', 'a2'])
diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst
--- a/doc/source/whatsnew.rst
+++ b/doc/source/whatsnew.rst
@@ -28,7 +28,8 @@
but failed if you make use the ``bool`` type (because that is rendered
as the C ``_Bool`` type, which doesn't exist in C++).
-* ``help(lib)`` and ``help(lib.myfunc)`` now give useful information.
+* ``help(lib)`` and ``help(lib.myfunc)`` now give useful information,
+ as well as ``dir(p)`` where ``p`` is a struct or pointer-to-struct.
v1.6
More information about the pypy-commit
mailing list