[pypy-commit] cffi cpy-extension: Full enums.
arigo
noreply at buildbot.pypy.org
Thu Jun 14 11:43:03 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: cpy-extension
Changeset: r323:eb296df46471
Date: 2012-06-14 11:42 +0200
http://bitbucket.org/cffi/cffi/changeset/eb296df46471/
Log: Full enums.
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -49,7 +49,7 @@
#
self.prnt('static PyMethodDef _cffi_methods[] = {')
self.generate("method")
- self.prnt(' {"_cffi_setup", _cffi_setup, METH_O},')
+ self.prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS},')
self.prnt(' {NULL, NULL} /* Sentinel */')
self.prnt('};')
self.prnt()
@@ -82,7 +82,7 @@
revmapping = dict([(value, key)
for (key, value) in self.typesdict.items()])
lst = [revmapping[i] for i in range(len(revmapping))]
- dct = module._cffi_setup(lst)
+ dct = module._cffi_setup(lst, ffiplatform.VerificationError)
del module._cffi_setup
module.__dict__.update(dct)
#
@@ -312,20 +312,25 @@
# ----------
# constants, likely declared with '#define'
- def generate_cpy_constant_decl(self, tp, name):
- is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
+ def _generate_chain_header(self, funcname, *vardecls):
prnt = self.prnt
- my_func_name = '_cffi_const_%s' % name
- prnt('static int %s(PyObject *dct)' % my_func_name)
+ prnt('static int %s(PyObject *dct)' % funcname)
prnt('{')
- if not is_int:
- prnt(' %s;' % tp.get_c_name(' i'))
- prnt(' PyObject *o;')
- prnt(' int res;')
+ for decl in vardecls:
+ prnt(' ' + decl)
if self.chained_list_constants is not None:
prnt(' if (%s(dct) < 0)' % self.chained_list_constants)
prnt(' return -1;')
- self.chained_list_constants = my_func_name
+ self.chained_list_constants = funcname
+
+ def _generate_cpy_const(self, is_int, name, tp=None):
+ vardecls = ['PyObject *o;',
+ 'int res;']
+ if not is_int:
+ vardecls.append('%s;' % tp.get_c_name(' i'))
+ self._generate_chain_header('_cffi_const_%s' % name, *vardecls)
+ #
+ prnt = self.prnt
if not is_int:
prnt(' i = (%s);' % (name,))
prnt(' o = %s;' % (self.convert_expr_from_c(tp, 'i'),))
@@ -345,12 +350,49 @@
prnt('}')
prnt()
+ def generate_cpy_constant_decl(self, tp, name):
+ is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
+ self._generate_cpy_const(is_int, name, tp)
+
generate_cpy_constant_method = generate_nothing
-
loading_cpy_constant = loaded_noop
loaded_cpy_constant = loaded_noop
# ----------
+ # enums
+
+ def generate_cpy_enum_decl(self, tp, name):
+ if tp.partial:
+ for enumerator in tp.enumerators:
+ self._generate_cpy_const(True, enumerator)
+ return
+ #
+ self._generate_chain_header('_cffi_enum_%s' % name)
+ prnt = self.prnt
+ for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
+ prnt(' if (%s != %d) {' % (enumerator, enumvalue))
+ prnt(' PyErr_Format(_cffi_VerificationError,')
+ prnt(' "in enum %s: %s has the real value %d, '
+ 'not %d",')
+ prnt(' "%s", "%s", (int)%s, %d);' % (
+ name, enumerator, enumerator, enumvalue))
+ prnt(' return -1;')
+ prnt(' }')
+ prnt(' return 0;')
+ prnt('}')
+ prnt()
+
+ generate_cpy_enum_method = generate_nothing
+ loading_cpy_enum = loaded_noop
+
+ def loaded_cpy_enum(self, tp, name, module):
+ if tp.partial:
+ enumvalues = [getattr(module, enumerator)
+ for enumerator in tp.enumerators]
+ tp.enumvalues = tuple(enumvalues)
+ tp.partial = False
+
+ # ----------
cffimod_header = r'''
#include <Python.h>
@@ -430,15 +472,21 @@
typedef struct _ctypedescr CTypeDescrObject;
static void **_cffi_exports;
-static PyObject *_cffi_types;
+static PyObject *_cffi_types, *_cffi_VerificationError;
static PyObject *_cffi_setup_custom(void); /* forward */
-static PyObject *_cffi_setup(PyObject *self, PyObject *arg)
+static PyObject *_cffi_setup(PyObject *self, PyObject *args)
{
- PyObject *module = PyImport_ImportModule("_ffi_backend");
+ PyObject *module;
PyObject *c_api_object;
+ if (!PyArg_ParseTuple(args, "OO", &_cffi_types, &_cffi_VerificationError))
+ return NULL;
+ Py_INCREF(_cffi_types);
+ Py_INCREF(_cffi_VerificationError);
+
+ module = PyImport_ImportModule("_ffi_backend");
if (module == NULL)
return NULL;
@@ -451,9 +499,6 @@
}
_cffi_exports = (void **)PyCObject_AsVoidPtr(c_api_object);
- Py_INCREF(arg);
- _cffi_types = arg;
-
return _cffi_setup_custom();
}
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -286,21 +286,18 @@
ffi = FFI()
ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };")
py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2')
- py.test.skip("in-progress")
ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
assert int(ffi.cast('enum ee', 'EE2')) == 11
assert int(ffi.cast('enum ee', 'EE3')) == -10
- py.test.raises(AttributeError, ffi.cast, 'enum ee', '__dotdotdot0__')
+ py.test.raises(ValueError, ffi.cast, 'enum ee', '__dotdotdot0__')
def test_full_enum():
- py.test.skip("in-progress")
ffi = FFI()
ffi.cdef("enum ee { EE1, EE2, EE3 };")
ffi.verify("enum ee { EE1, EE2, EE3 };")
- for real in [
- "enum ee { EE1, EE2 };"
- "enum ee { EE1, EE3, EE2 };"
- ]:
- py.test.raises(VerificationError, ffi.verify, real)
+ py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };")
+ e = py.test.raises(VerificationError, ffi.verify,
+ "enum ee { EE1, EE3, EE2 };")
+ assert str(e.value) == 'in enum ee: EE2 has the real value 2, not 1'
# extra items cannot be seen and have no bad consequence anyway
ffi.verify("enum ee { EE1, EE2, EE3, EE4 };")
More information about the pypy-commit
mailing list