Author: Armin Rigo <ar...@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 };") _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit