[pypy-commit] cffi python3-port: An attempt to port cffi to python3.
amauryfa
noreply at buildbot.pypy.org
Sun Jul 29 00:38:47 CEST 2012
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: python3-port
Changeset: r738:203dc42ec877
Date: 2012-07-29 00:37 +0200
http://bitbucket.org/cffi/cffi/changeset/203dc42ec877/
Log: An attempt to port cffi to python3. Most tests are passing, yeah!
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -22,6 +22,41 @@
# define USE__THREAD
#endif
+#if PY_MAJOR_VERSION >= 3
+# define PyText_Type PyUnicode_Type
+# define PyText_Check PyUnicode_Check
+# define PyText_FromFormat PyUnicode_FromFormat
+# define PyText_AsUTF8 PyUnicode_AsUTF8
+# define PyText_GetSize PyUnicode_GetSize
+# define PyText_FromString PyUnicode_FromString
+# define PyText_FromStringAndSize PyUnicode_FromStringAndSize
+# define PyText_InternInPlace PyUnicode_InternInPlace
+#else
+# define PyText_Type PyString_Type
+# define PyText_Check PyString_Check
+# define PyText_FromFormat PyString_FromFormat
+# define PyText_AsUTF8 PyString_AsString
+# define PyText_GetSize PyString_GetSize
+# define PyText_FromString PyString_FromString
+# define PyText_FromStringAndSize PyString_FromStringAndSize
+# define PyText_InternInPlace PyString_InternInPlace
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+# define PyInt_FromLong PyLong_FromLong
+# define PyInt_FromSsize_t PyLong_FromSsize_t
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+/* This is the default on Python3 and constant has been removed. */
+# define Py_TPFLAGS_CHECKTYPES 0
+#endif
+
+#if PY_MAJOR_VERSION < 3
+#define PyCapsule_New(pointer, name, destructor) \
+ (PyCObject_FromVoidPtr(pointer, destructor))
+#endif
+
/************************************************************/
/* base type flag: exactly one of the following: */
@@ -208,7 +243,7 @@
static PyObject *
ctypedescr_repr(CTypeDescrObject *ct)
{
- return PyString_FromFormat("<ctype '%s'>", ct->ct_name);
+ return PyText_FromFormat("<ctype '%s'>", ct->ct_name);
}
static void
@@ -277,7 +312,7 @@
PyObject *d_key, *d_value;
while (PyDict_Next(ct->ct_stuff, &i, &d_key, &d_value)) {
if (d_value == (PyObject *)cf)
- return PyString_AsString(d_key);
+ return PyText_AsUTF8(d_key);
}
return NULL;
}
@@ -300,10 +335,10 @@
#define OFF(x) offsetof(CFieldObject, x)
static PyMemberDef cfield_members[] = {
- {"type", T_OBJECT, OFF(cf_type), RO},
- {"offset", T_PYSSIZET, OFF(cf_offset), RO},
- {"bitshift", T_SHORT, OFF(cf_bitshift), RO},
- {"bitsize", T_SHORT, OFF(cf_bitsize), RO},
+ {"type", T_OBJECT, OFF(cf_type), READONLY},
+ {"offset", T_PYSSIZET, OFF(cf_offset), READONLY},
+ {"bitshift", T_SHORT, OFF(cf_bitshift), READONLY},
+ {"bitsize", T_SHORT, OFF(cf_bitsize), READONLY},
{NULL} /* Sentinel */
};
#undef OFF
@@ -349,10 +384,13 @@
Like PyLong_AsLongLong(), this version accepts a Python int too, and
does convertions from other types of objects. The difference is that
this version refuses floats. */
+#if PY_MAJOR_VERSION < 3
if (PyInt_Check(ob)) {
return PyInt_AS_LONG(ob);
}
- else if (PyLong_Check(ob)) {
+ else
+#endif
+ if (PyLong_Check(ob)) {
return PyLong_AsLongLong(ob);
}
else {
@@ -369,7 +407,11 @@
if (io == NULL)
return -1;
+#if PY_MAJOR_VERSION < 3
if (PyInt_Check(io) || PyLong_Check(io)) {
+#else
+ if (PyLong_Check(io)) {
+#endif
res = _my_PyLong_AsLongLong(io);
}
else {
@@ -389,13 +431,16 @@
does convertions from other types of objects. If 'strict', complains
with OverflowError and refuses floats. If '!strict', rounds floats
and masks the result. */
+#if PY_MAJOR_VERSION < 3
if (PyInt_Check(ob)) {
long value1 = PyInt_AS_LONG(ob);
if (strict && value1 < 0)
goto negative;
return (unsigned PY_LONG_LONG)(PY_LONG_LONG)value1;
}
- else if (PyLong_Check(ob)) {
+ else
+#endif
+ if (PyLong_Check(ob)) {
if (strict) {
if (_PyLong_Sign(ob) < 0)
goto negative;
@@ -419,7 +464,11 @@
if (io == NULL)
return (unsigned PY_LONG_LONG)-1;
+#if PY_MAJOR_VERSION < 3
if (PyInt_Check(io) || PyLong_Check(io)) {
+#else
+ if (PyLong_Check(io)) {
+#endif
res = _my_PyLong_AsUnsignedLongLong(io, strict);
}
else {
@@ -531,9 +580,9 @@
{
PyObject *d_value;
- if (PyString_AS_STRING(ob)[0] == '#') {
- char *number = PyString_AS_STRING(ob) + 1; /* strip initial '#' */
- PyObject *ob2 = PyString_FromString(number);
+ if (PyText_AsUTF8(ob)[0] == '#') {
+ char *number = PyText_AsUTF8(ob) + 1; /* strip initial '#' */
+ PyObject *ob2 = PyText_FromString(number);
if (ob2 == NULL)
return NULL;
@@ -544,9 +593,8 @@
d_value = PyDict_GetItem(PyTuple_GET_ITEM(ct->ct_stuff, 0), ob);
if (d_value == NULL) {
PyErr_Format(PyExc_ValueError,
- "'%s' is not an enumerator for %s",
- PyString_AS_STRING(ob),
- ct->ct_name);
+ "%R is not an enumerator for %s",
+ ob, ct->ct_name);
return NULL;
}
Py_INCREF(d_value);
@@ -585,7 +633,7 @@
if (d_value != NULL)
Py_INCREF(d_value);
else
- d_value = PyString_FromFormat("#%d", (int)value);
+ d_value = PyText_FromFormat("#%d", (int)value);
return d_value;
}
else if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
@@ -607,7 +655,7 @@
}
else if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
if (ct->ct_size == sizeof(char))
- return PyString_FromStringAndSize(data, 1);
+ return PyBytes_FromStringAndSize(data, 1);
#ifdef HAVE_WCHAR_H
else
return _my_PyUnicode_FromWideChar((wchar_t *)data, 1);
@@ -661,24 +709,32 @@
s = PyObject_Str(init);
if (s == NULL)
return -1;
- PyErr_Format(PyExc_OverflowError, "integer %s does not fit '%s'",
- PyString_AS_STRING(s), ct_name);
+ PyErr_Format(PyExc_OverflowError, "integer %S does not fit '%s'",
+ s, ct_name);
Py_DECREF(s);
return -1;
}
static int _convert_to_char(PyObject *init)
{
- if (PyString_Check(init) && PyString_GET_SIZE(init) == 1) {
- return (unsigned char)(PyString_AS_STRING(init)[0]);
+ if (PyBytes_Check(init) && PyBytes_GET_SIZE(init) == 1) {
+ return (unsigned char)(PyBytes_AS_STRING(init)[0]);
}
+#if PY_MAJOR_VERSION >= 3
+ if (PyLong_Check(init)) {
+ long value = PyLong_AsLong(init);
+ if (value >= 0 && value < 256) {
+ return (unsigned char)value;
+ }
+ }
+#endif
if (CData_Check(init) &&
(((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR) &&
(((CDataObject *)init)->c_type->ct_size == sizeof(char))) {
return *(unsigned char *)((CDataObject *)init)->c_data;
}
PyErr_Format(PyExc_TypeError,
- "initializer for ctype 'char' must be a string of length 1, "
+ "initializer for ctype 'char' must be a bytes string of length 1, "
"not %.200s", Py_TYPE(init)->tp_name);
return -1;
}
@@ -765,11 +821,11 @@
if (ctitem->ct_size == sizeof(char)) {
char *srcdata;
Py_ssize_t n;
- if (!PyString_Check(init)) {
- expected = "str or list or tuple";
+ if (!PyBytes_Check(init)) {
+ expected = "bytes or list or tuple";
goto cannot_convert;
}
- n = PyString_GET_SIZE(init);
+ n = PyBytes_GET_SIZE(init);
if (ct->ct_length >= 0 && n > ct->ct_length) {
PyErr_Format(PyExc_IndexError,
"initializer string is too long for '%s' "
@@ -778,7 +834,7 @@
}
if (n != ct->ct_length)
n++;
- srcdata = PyString_AS_STRING(init);
+ srcdata = PyBytes_AS_STRING(init);
memcpy(data, srcdata, n);
return 0;
}
@@ -848,7 +904,7 @@
else {
PyObject *ob;
PyErr_Clear();
- if (!PyString_Check(init)) {
+ if (!PyText_Check(init)) {
expected = "str or int";
goto cannot_convert;
}
@@ -1007,11 +1063,9 @@
sfmax = PyObject_Str(lfmax);
if (sfmax == NULL) goto skip;
PyErr_Format(PyExc_OverflowError,
- "value %s outside the range allowed by the "
- "bit field width: %s <= x <= %s",
- PyString_AS_STRING(svalue),
- PyString_AS_STRING(sfmin),
- PyString_AS_STRING(sfmax));
+ "value %S outside the range allowed by the "
+ "bit field width: %S <= x <= %S",
+ svalue, sfmin, sfmax);
skip:
Py_XDECREF(svalue);
Py_XDECREF(sfmin);
@@ -1113,14 +1167,14 @@
Py_DECREF(o);
if (s == NULL)
return NULL;
- p = PyString_AS_STRING(s);
+ p = PyText_AsUTF8(s);
}
else {
if (cd->c_data != NULL) {
- s = PyString_FromFormat("%p", cd->c_data);
+ s = PyText_FromFormat("%p", cd->c_data);
if (s == NULL)
return NULL;
- p = PyString_AS_STRING(s);
+ p = PyText_AsUTF8(s);
}
else
p = "NULL";
@@ -1132,17 +1186,17 @@
extra = " &";
else
extra = "";
- result = PyString_FromFormat("<cdata '%s%s' %s>",
- cd->c_type->ct_name, extra, p);
+ result = PyText_FromFormat("<cdata '%s%s' %s>",
+ cd->c_type->ct_name, extra, p);
Py_XDECREF(s);
return result;
}
-static PyObject *cdata_str(CDataObject *cd)
+static PyObject *cdata_get_value(CDataObject *cd)
{
if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR &&
cd->c_type->ct_size == sizeof(char)) {
- return PyString_FromStringAndSize(cd->c_data, 1);
+ return PyBytes_FromStringAndSize(cd->c_data, 1);
}
else if (cd->c_type->ct_itemdescr != NULL &&
cd->c_type->ct_itemdescr->ct_flags & CT_PRIMITIVE_CHAR &&
@@ -1162,8 +1216,7 @@
PyObject *s = cdata_repr(cd);
if (s != NULL) {
PyErr_Format(PyExc_RuntimeError,
- "cannot use str() on %s",
- PyString_AS_STRING(s));
+ "cannot use str() on %S", s);
Py_DECREF(s);
}
return NULL;
@@ -1171,18 +1224,10 @@
length = strlen(cd->c_data);
}
- return PyString_FromStringAndSize(cd->c_data, length);
+ return PyBytes_FromStringAndSize(cd->c_data, length);
}
- else if (cd->c_type->ct_flags & CT_IS_ENUM)
- return convert_to_object(cd->c_data, cd->c_type);
- else
- return Py_TYPE(cd)->tp_repr((PyObject *)cd);
-}
-
#ifdef HAVE_WCHAR_H
-static PyObject *cdata_unicode(CDataObject *cd)
-{
- if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR &&
+ else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR &&
cd->c_type->ct_size == sizeof(wchar_t)) {
return _my_PyUnicode_FromWideChar((wchar_t *)cd->c_data, 1);
}
@@ -1203,8 +1248,7 @@
PyObject *s = cdata_repr(cd);
if (s != NULL) {
PyErr_Format(PyExc_RuntimeError,
- "cannot use unicode() on %s",
- PyString_AS_STRING(s));
+ "cannot use unicode() on %S", s);
Py_DECREF(s);
}
return NULL;
@@ -1216,10 +1260,20 @@
return _my_PyUnicode_FromWideChar((wchar_t *)cd->c_data, length);
}
+#endif
+ else {
+ Py_INCREF(cd);
+ return (PyObject *)cd;
+ }
+}
+
+static PyObject *cdata_str(CDataObject *cd)
+{
+ if (cd->c_type->ct_flags & CT_IS_ENUM)
+ return convert_to_object(cd->c_data, cd->c_type);
else
return Py_TYPE(cd)->tp_repr((PyObject *)cd);
}
-#endif
static PyObject *cdataowning_repr(CDataObject *cd)
{
@@ -1233,8 +1287,8 @@
else
size = cd->c_type->ct_size;
- return PyString_FromFormat("<cdata '%s' owning %zd bytes>",
- cd->c_type->ct_name, size);
+ return PyText_FromFormat("<cdata '%s' owning %zd bytes>",
+ cd->c_type->ct_name, size);
callback_repr:
{
@@ -1246,8 +1300,8 @@
s = PyObject_Repr(PyTuple_GET_ITEM(args, 1));
if (s == NULL)
return NULL;
- res = PyString_FromFormat("<cdata '%s' calling %s>",
- cd->c_type->ct_name, PyString_AsString(s));
+ res = PyText_FromFormat("<cdata '%s' calling %s>",
+ cd->c_type->ct_name, PyText_AsUTF8(s));
Py_DECREF(s);
return res;
}
@@ -1281,7 +1335,11 @@
}
else if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
PyObject *o = convert_to_object(cd->c_data, cd->c_type);
+#if PY_MAJOR_VERSION < 3
PyObject *r = o ? PyNumber_Int(o) : NULL;
+#else
+ PyObject *r = o ? PyNumber_Long(o) : NULL;
+#endif
Py_XDECREF(o);
return r;
}
@@ -1290,6 +1348,7 @@
return NULL;
}
+#if PY_MAJOR_VERSION < 3
static PyObject *cdata_long(CDataObject *cd)
{
PyObject *res = cdata_int(cd);
@@ -1300,6 +1359,7 @@
}
return res;
}
+#endif
static PyObject *cdata_float(CDataObject *cd)
{
@@ -1521,7 +1581,11 @@
return NULL;
}
diff = (cdv->c_data - cdw->c_data) / ct->ct_itemdescr->ct_size;
+#if PY_MAJOR_VERSION < 3
return PyInt_FromSsize_t(diff);
+#else
+ return PyLong_FromSsize_t(diff);
+#endif
}
return _cdata_add_or_sub(v, w, -1);
@@ -1682,7 +1746,11 @@
}
PyTuple_SET_ITEM(fvarargs, i, (PyObject *)ct);
}
+#if PY_MAJOR_VERSION < 3
fabi = PyInt_AS_LONG(PyTuple_GET_ITEM(signature, 0));
+#else
+ fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0));
+#endif
cif_descr = fb_prepare_cif(fvarargs, fresult, fabi);
if (cif_descr == NULL)
goto error;
@@ -1711,9 +1779,9 @@
if ((argtype->ct_flags & CT_POINTER) &&
(argtype->ct_itemdescr->ct_flags & CT_PRIMITIVE_CHAR)) {
if (argtype->ct_itemdescr->ct_size == sizeof(char)) {
- if (PyString_Check(obj)) {
+ if (PyText_Check(obj)) {
/* special case: Python string -> cdata 'char *' */
- *(char **)data = PyString_AS_STRING(obj);
+ *(char **)data = PyText_AsUTF8(obj);
continue;
}
}
@@ -1786,7 +1854,9 @@
(binaryfunc)cdata_add, /*nb_add*/
(binaryfunc)cdata_sub, /*nb_subtract*/
0, /*nb_multiply*/
+#if PY_MAJOR_VERSION < 3
0, /*nb_divide*/
+#endif
0, /*nb_remainder*/
0, /*nb_divmod*/
0, /*nb_power*/
@@ -1800,12 +1870,14 @@
0, /*nb_and*/
0, /*nb_xor*/
0, /*nb_or*/
+#if PY_MAJOR_VERSION < 3
0, /*nb_coerce*/
+ (unaryfunc)cdata_long, /*nb_long*/
+#else
(unaryfunc)cdata_int, /*nb_int*/
- (unaryfunc)cdata_long, /*nb_long*/
+ 0, /*nb_reserved*/
+#endif
(unaryfunc)cdata_float, /*nb_float*/
- 0, /*nb_oct*/
- 0, /*nb_hex*/
};
static PyMappingMethods CData_as_mapping = {
@@ -1821,10 +1893,14 @@
};
static PyMethodDef CData_methods[] = {
- {"__unicode__", (PyCFunction)cdata_unicode, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
+static PyGetSetDef CData_getset[] = {
+ {"value", (getter)cdata_get_value, NULL, NULL},
+ {0}
+};
+
static PyTypeObject CData_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_cffi_backend.CData",
@@ -1854,6 +1930,8 @@
(getiterfunc)cdata_iter, /* tp_iter */
0, /* tp_iternext */
CData_methods, /* tp_methods */
+ 0, /* tp_members */
+ CData_getset, /* tp_getset */
};
static PyTypeObject CDataOwning_Type = {
@@ -2039,9 +2117,9 @@
if (PyList_Check(init) || PyTuple_Check(init)) {
explicitlength = PySequence_Fast_GET_SIZE(init);
}
- else if (PyString_Check(init)) {
+ else if (PyBytes_Check(init)) {
/* from a string, we add the null terminator */
- explicitlength = PyString_GET_SIZE(init) + 1;
+ explicitlength = PyBytes_GET_SIZE(init) + 1;
}
else if (PyUnicode_Check(init)) {
/* from a unicode, we add the null terminator */
@@ -2142,7 +2220,7 @@
(CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY)) {
value = (Py_intptr_t)((CDataObject *)ob)->c_data;
}
- else if (PyString_Check(ob)) {
+ else if (PyText_Check(ob)) {
if (ct->ct_flags & CT_IS_ENUM) {
ob = convert_enum_string_to_int(ct, ob);
if (ob == NULL)
@@ -2152,13 +2230,24 @@
return cd;
}
else {
- if (PyString_GET_SIZE(ob) != 1) {
+#if PY_MAJOR_VERSION < 3
+ if (PyString_GetSize(ob) != 1) {
PyErr_Format(PyExc_TypeError,
"cannot cast string of length %zd to ctype '%s'",
- PyString_GET_SIZE(ob), ct->ct_name);
+ PyString_GetSize(ob), ct->ct_name);
return NULL;
}
- value = (unsigned char)PyString_AS_STRING(ob)[0];
+ value = (unsigned char)PyString_AsString(ob)[0];
+#else
+ wchar_t ordinal;
+ if (_my_PyUnicode_AsSingleWideChar(ob, &ordinal) < 0) {
+ PyErr_Format(PyExc_TypeError,
+ "cannot cast unicode of length %zd to ctype '%s'",
+ PyUnicode_GET_SIZE(ob), ct->ct_name);
+ return NULL;
+ }
+ value = (long)ordinal;
+#endif
}
}
#ifdef HAVE_WCHAR_H
@@ -2173,6 +2262,9 @@
value = (long)ordinal;
}
#endif
+ else if (PyBytes_Check(ob)) {
+ value = (unsigned char)_convert_to_char(ob);
+ }
else {
value = _my_PyLong_AsUnsignedLongLong(ob, 0);
if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
@@ -2236,12 +2328,12 @@
Py_INCREF(io);
}
- if (PyString_Check(io)) {
- if (PyString_GET_SIZE(io) != 1) {
+ if (PyBytes_Check(io)) {
+ if (PyBytes_GET_SIZE(io) != 1) {
Py_DECREF(io);
goto cannot_cast;
}
- value = (unsigned char)PyString_AS_STRING(io)[0];
+ value = (unsigned char)PyBytes_AS_STRING(io)[0];
}
else {
value = PyFloat_AsDouble(io);
@@ -2289,7 +2381,7 @@
static PyObject *dl_repr(DynLibObject *dlobj)
{
- return PyString_FromFormat("<clibrary '%s'>", dlobj->dl_name);
+ return PyText_FromFormat("<clibrary '%s'>", dlobj->dl_name);
}
static PyObject *dl_load_function(DynLibObject *dlobj, PyObject *args)
@@ -2781,15 +2873,15 @@
CFieldObject *cf;
if (!PyArg_ParseTuple(PyList_GET_ITEM(fields, i), "O!O!|ii:list item",
- &PyString_Type, &fname,
+ &PyText_Type, &fname,
&CTypeDescr_Type, &ftype,
&fbitsize, &foffset))
goto error;
if (ftype->ct_size < 0) {
PyErr_Format(PyExc_TypeError,
- "field '%s.%s' has ctype '%s' of unknown size",
- ct->ct_name, PyString_AS_STRING(fname),
+ "field '%s.%S' has ctype '%s' of unknown size",
+ ct->ct_name, fname,
ftype->ct_name);
goto error;
}
@@ -2827,8 +2919,8 @@
#endif
fbitsize == 0 ||
fbitsize > 8 * ftype->ct_size) {
- PyErr_Format(PyExc_TypeError, "invalid bit field '%s'",
- PyString_AS_STRING(fname));
+ PyErr_Format(PyExc_TypeError, "invalid bit field %R",
+ fname);
goto error;
}
if (prev_bit_position > 0) {
@@ -2862,7 +2954,7 @@
cf->cf_bitsize = fbitsize;
Py_INCREF(fname);
- PyString_InternInPlace(&fname);
+ PyText_InternInPlace(&fname);
err = PyDict_SetItem(interned_fields, fname, (PyObject *)cf);
Py_DECREF(fname);
Py_DECREF(cf);
@@ -2870,8 +2962,8 @@
goto error;
if (PyDict_Size(interned_fields) != i + 1) {
- PyErr_Format(PyExc_KeyError, "duplicate field name '%s'",
- PyString_AS_STRING(fname));
+ PyErr_Format(PyExc_KeyError, "duplicate field name %R",
+ fname);
goto error;
}
@@ -3452,8 +3544,8 @@
PyErr_WriteUnraisable(py_ob);
if (SIGNATURE(1)->ct_size > 0) {
py_rawerr = PyTuple_GET_ITEM(cb_args, 2);
- memcpy(result, PyString_AS_STRING(py_rawerr),
- PyString_GET_SIZE(py_rawerr));
+ memcpy(result, PyBytes_AS_STRING(py_rawerr),
+ PyBytes_GET_SIZE(py_rawerr));
}
goto done;
}
@@ -3491,13 +3583,12 @@
size = ctresult->ct_size;
if (size < (Py_ssize_t)sizeof(ffi_arg))
size = sizeof(ffi_arg);
- py_rawerr = PyString_FromStringAndSize(NULL, size);
+ py_rawerr = PyBytes_FromStringAndSize(NULL, size);
if (py_rawerr == NULL)
return NULL;
- memset(PyString_AS_STRING(py_rawerr), 0, size);
if (error_ob != Py_None) {
if (convert_from_object_fficallback(
- PyString_AS_STRING(py_rawerr), ctresult, error_ob) < 0) {
+ PyBytes_AS_STRING(py_rawerr), ctresult, error_ob) < 0) {
Py_DECREF(py_rawerr);
return NULL;
}
@@ -3699,8 +3790,7 @@
static PyObject *b_getcname(PyObject *self, PyObject *args)
{
CTypeDescrObject *ct;
- char *replace_with, *p;
- PyObject *s;
+ char *replace_with, *p, *s;
Py_ssize_t namelen, replacelen;
if (!PyArg_ParseTuple(args, "O!s:getcname",
@@ -3709,11 +3799,7 @@
namelen = strlen(ct->ct_name);
replacelen = strlen(replace_with);
- s = PyString_FromStringAndSize(NULL, namelen + replacelen);
- if (s == NULL)
- return NULL;
-
- p = PyString_AS_STRING(s);
+ s = p = alloca(namelen + replacelen + 1);
memcpy(p, ct->ct_name, ct->ct_name_position);
p += ct->ct_name_position;
memcpy(p, replace_with, replacelen);
@@ -3721,7 +3807,7 @@
memcpy(p, ct->ct_name + ct->ct_name_position,
namelen - ct->ct_name_position);
- return s;
+ return PyText_FromStringAndSize(s, namelen + replacelen);
}
static PyObject *b_buffer(PyObject *self, PyObject *args)
@@ -3752,7 +3838,17 @@
cd->c_type->ct_name);
return NULL;
}
+#if PY_MAJOR_VERSION < 3
return PyBuffer_FromReadWriteMemory(cd->c_data, size);
+#else
+ {
+ Py_buffer view;
+ if (PyBuffer_FillInfo(&view, NULL, cd->c_data, size,
+ /*readonly=*/0, PyBUF_WRITABLE) < 0)
+ return NULL;
+ return PyMemoryView_FromBuffer(&view);
+ }
+#endif
}
static PyObject *b_get_errno(PyObject *self, PyObject *noarg)
@@ -3956,7 +4052,7 @@
{"get_errno", b_get_errno, METH_NOARGS},
{"set_errno", b_set_errno, METH_VARARGS},
{"_testfunc", b__testfunc, METH_VARARGS},
- {NULL, NULL} /* Sentinel */
+ {NULL, NULL} /* Sentinel */
};
/************************************************************/
@@ -3964,8 +4060,8 @@
static char *_cffi_to_c_char_p(PyObject *obj)
{
- if (PyString_Check(obj)) {
- return PyString_AS_STRING(obj);
+ if (PyBytes_Check(obj)) {
+ return PyBytes_AS_STRING(obj);
}
if (CData_Check(obj)) {
return ((CDataObject *)obj)->c_data;
@@ -3974,9 +4070,15 @@
return NULL;
}
+#if PY_MAJOR_VERSION < 3
+# define PyCffiInt_AsLong PyInt_AsLong
+#else
+# define PyCffiInt_AsLong PyLong_AsLong
+#endif
+
#define _cffi_to_c_PRIMITIVE(TARGETNAME, TARGET) \
static TARGET _cffi_to_c_##TARGETNAME(PyObject *obj) { \
- long tmp = PyInt_AsLong(obj); \
+ long tmp = PyCffiInt_AsLong(obj); \
if (tmp != (TARGET)tmp) \
return (TARGET)_convert_overflow(obj, #TARGET); \
return (TARGET)tmp; \
@@ -4049,7 +4151,7 @@
}
static PyObject *_cffi_from_c_char(char x) {
- return PyString_FromStringAndSize(&x, 1);
+ return PyBytes_FromStringAndSize(&x, 1);
}
#ifdef HAVE_WCHAR_H
@@ -4094,54 +4196,80 @@
/************************************************************/
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef FFIBackendModuleDef = {
+ PyModuleDef_HEAD_INIT,
+ "_cffi_backend",
+ NULL,
+ -1,
+ FFIBackendMethods,
+ NULL, NULL, NULL, NULL
+};
+#define INITERROR return NULL
+
+PyObject *
+PyInit__cffi_backend(void)
+#else
+#define INITERROR return
+
void init_cffi_backend(void)
+#endif
{
PyObject *m, *v;
v = PySys_GetObject("version");
- if (v == NULL || !PyString_Check(v) ||
- strncmp(PyString_AS_STRING(v), PY_VERSION, 3) != 0) {
+ if (v == NULL || !PyText_Check(v) ||
+ strncmp(PyText_AsUTF8(v), PY_VERSION, 3) != 0) {
PyErr_Format(PyExc_ImportError,
"this module was compiled for Python %c%c%c",
PY_VERSION[0], PY_VERSION[1], PY_VERSION[2]);
- return;
+ INITERROR;
}
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&FFIBackendModuleDef);
+#else
m = Py_InitModule("_cffi_backend", FFIBackendMethods);
+#endif
+
if (m == NULL)
- return;
+ INITERROR;
if (PyType_Ready(&dl_type) < 0)
- return;
+ INITERROR;
if (PyType_Ready(&CTypeDescr_Type) < 0)
- return;
+ INITERROR;
if (PyType_Ready(&CField_Type) < 0)
- return;
+ INITERROR;
if (PyType_Ready(&CData_Type) < 0)
- return;
+ INITERROR;
if (PyType_Ready(&CDataOwning_Type) < 0)
- return;
+ INITERROR;
if (PyType_Ready(&CDataIter_Type) < 0)
- return;
-
- v = PyCObject_FromVoidPtr((void *)cffi_exports, NULL);
+ INITERROR;
+
+ v = PyCapsule_New((void *)cffi_exports, "cffi", NULL);
if (v == NULL || PyModule_AddObject(m, "_C_API", v) < 0)
- return;
-
- v = PyString_FromString("0.2.1");
+ INITERROR;
+
+ v = PyText_FromString("0.2.1");
if (v == NULL || PyModule_AddObject(m, "__version__", v) < 0)
- return;
+ INITERROR;
#if defined(MS_WIN32) && !defined(_WIN64)
v = PyInt_FromLong(FFI_STDCALL);
if (v == NULL || PyModule_AddObject(m, "FFI_STDCALL", v) < 0)
- return;
+ INITERROR;
#endif
v = PyInt_FromLong(FFI_DEFAULT_ABI);
if (v == NULL || PyModule_AddObject(m, "FFI_DEFAULT_ABI", v) < 0)
- return;
+ INITERROR;
Py_INCREF(v);
if (PyModule_AddObject(m, "FFI_CDECL", v) < 0) /* win32 name */
- return;
+ INITERROR;
init_errno();
+
+#if PY_MAJOR_VERSION >= 3
+ return m;
+#endif
}
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -1,4 +1,4 @@
-import new
+import types
class FFIError(Exception):
pass
@@ -38,7 +38,7 @@
if backend is None:
try:
import _cffi_backend as backend
- except ImportError, e:
+ except ImportError as e:
import warnings
warnings.warn("import _cffi_backend: %s\n"
"Falling back to the ctypes backend." % (e,))
@@ -47,8 +47,8 @@
self._backend = backend
self._parser = cparser.Parser()
self._cached_btypes = {}
- self._parsed_types = new.module('parsed_types').__dict__
- self._new_types = new.module('new_types').__dict__
+ self._parsed_types = types.ModuleType('parsed_types').__dict__
+ self._new_types = types.ModuleType('new_types').__dict__
self._function_caches = []
self._cdefsources = []
if hasattr(backend, 'set_ffi'):
@@ -113,7 +113,7 @@
corresponding Python type: <class 'ffi.CData<...>'>.
It can also be used on 'cdata' instance to get its C type.
"""
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
return self._typeof(cdecl)
else:
return self._backend.typeof(cdecl)
@@ -122,7 +122,7 @@
"""Return the size in bytes of the argument. It can be a
string naming a C type, or a 'cdata' instance.
"""
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
BType = self._typeof(cdecl)
return self._backend.sizeof(BType)
else:
@@ -132,7 +132,7 @@
"""Return the natural alignment size in bytes of the C type
given as a string.
"""
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
cdecl = self._typeof(cdecl)
return self._backend.alignof(cdecl)
@@ -140,7 +140,7 @@
"""Return the offset of the named field inside the given
structure, which must be given as a C type name.
"""
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
cdecl = self._typeof(cdecl)
return self._backend.offsetof(cdecl, fieldname)
@@ -167,7 +167,7 @@
about that when copying the pointer to the memory somewhere
else, e.g. into another structure.
"""
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
cdecl = self._typeof(cdecl)
return self._backend.newp(cdecl, init)
@@ -176,7 +176,7 @@
type initialized with the given 'source'. The source is
casted between integers or pointers of any type.
"""
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
cdecl = self._typeof(cdecl)
return self._backend.cast(cdecl, source)
@@ -196,7 +196,7 @@
"""
if not callable(python_callable):
raise TypeError("the 'python_callable' argument is not callable")
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
cdecl = self._typeof(cdecl, consider_function_as_funcptr=True)
return self._backend.callback(cdecl, python_callable, error)
@@ -206,7 +206,7 @@
extra text to append (or insert for more complicated C types), like
a variable name, or '*' to get actually the C type 'pointer-to-cdecl'.
"""
- if isinstance(cdecl, basestring):
+ if isinstance(cdecl, str):
cdecl = self._typeof(cdecl)
replace_with = replace_with.strip()
if (replace_with.startswith('*')
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -1,5 +1,13 @@
import ctypes, ctypes.util, operator
from . import model
+import sys
+
+if sys.version < '3':
+ integer_types = (int, long)
+ bytes = str
+else:
+ integer_types = (int,)
+ xrange = range
class CTypesData(object):
__slots__ = []
@@ -48,6 +56,7 @@
@classmethod
def _fix_class(cls):
cls.__name__ = 'CData<%s>' % (cls._get_c_name(),)
+ cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),)
cls.__module__ = 'ffi'
def _get_own_repr(self):
@@ -162,7 +171,7 @@
address = 0
elif isinstance(source, CTypesData):
address = source._cast_to_integer()
- elif isinstance(source, (int, long)):
+ elif isinstance(source, integer_types):
address = source
else:
raise TypeError("bad type for cast to %r: %r" %
@@ -187,6 +196,9 @@
def __nonzero__(self):
return bool(self._address)
+
+ def __bool__(self):
+ return bool(self._address)
@classmethod
def _to_ctypes(cls, value):
@@ -318,11 +330,11 @@
is_signed = (ctype(-1).value == -1)
#
def _cast_source_to_int(source):
- if isinstance(source, (int, long, float)):
+ if isinstance(source, (integer_types, float)):
source = int(source)
elif isinstance(source, CTypesData):
source = source._cast_to_integer()
- elif isinstance(source, str):
+ elif isinstance(source, bytes):
source = ord(source)
elif source is None:
source = 0
@@ -358,11 +370,12 @@
@classmethod
def _cast_from(cls, source):
source = _cast_source_to_int(source)
- source = chr(source & 0xFF)
+ source = chr(source & 0xFF).encode('latin1')
return cls(source)
def __int__(self):
return ord(self._value)
- def __str__(self):
+ @property
+ def value(self):
return self._value
if kind == 'float':
@@ -389,7 +402,7 @@
if kind == 'int':
@staticmethod
def _to_ctypes(x):
- if not isinstance(x, (int, long)):
+ if not isinstance(x, integer_types):
if isinstance(x, CTypesData):
x = int(x)
else:
@@ -406,17 +419,19 @@
if kind == 'char':
@staticmethod
def _to_ctypes(x):
- if isinstance(x, str) and len(x) == 1:
+ if isinstance(x, bytes) and len(x) == 1:
return x
if isinstance(x, CTypesPrimitive): # <CData <char>>
return x._value
+ if sys.version >= '3' and isinstance(x, int):
+ return x
raise TypeError("character expected, got %s" %
type(x).__name__)
if kind == 'float':
@staticmethod
def _to_ctypes(x):
- if not isinstance(x, (int, long, float, CTypesData)):
+ if not isinstance(x, (integer_types, float, CTypesData)):
raise TypeError("float expected, got %s" %
type(x).__name__)
return ctype(x).value
@@ -459,14 +474,14 @@
self._own = True
def __add__(self, other):
- if isinstance(other, (int, long)):
+ if isinstance(other, integer_types):
return self._new_pointer_at(self._address +
other * self._bitem_size)
else:
return NotImplemented
def __sub__(self, other):
- if isinstance(other, (int, long)):
+ if isinstance(other, integer_types):
return self._new_pointer_at(self._address -
other * self._bitem_size)
elif type(self) is type(other):
@@ -483,14 +498,16 @@
self._as_ctype_ptr[index] = BItem._to_ctypes(value)
if kind == 'charp':
- def __str__(self):
+ @property
+ def value(self):
n = 0
- while self._as_ctype_ptr[n] != '\x00':
+ while self._as_ctype_ptr[n] != b'\x00':
n += 1
- return ''.join([self._as_ctype_ptr[i] for i in range(n)])
+ chars = [self._as_ctype_ptr[i] for i in range(n)]
+ return b''.join(chars)
@classmethod
def _arg_to_ctypes(cls, value):
- if isinstance(value, str):
+ if isinstance(value, bytes):
return ctypes.c_char_p(value)
else:
return super(CTypesPtr, cls)._arg_to_ctypes(value)
@@ -529,11 +546,11 @@
def __init__(self, init):
if length is None:
- if isinstance(init, (int, long)):
+ if isinstance(init, integer_types):
len1 = init
init = None
else:
- extra_null = (kind == 'char' and isinstance(init, str))
+ extra_null = (kind == 'char' and isinstance(init, bytes))
init = tuple(init)
len1 = len(init) + extra_null
self._ctype = BItem._ctype * len1
@@ -568,10 +585,11 @@
self._blob[index] = BItem._to_ctypes(value)
if kind == 'char':
- def __str__(self):
- s = ''.join(self._blob)
+ @property
+ def value(self):
+ s = b''.join(self._blob)
try:
- s = s[:s.index('\x00')]
+ s = s[:s.index(b'\x00')]
except ValueError:
pass
return s
@@ -598,7 +616,7 @@
return CTypesPtr._arg_to_ctypes(value)
def __add__(self, other):
- if isinstance(other, (int, long)):
+ if isinstance(other, integer_types):
return CTypesPtr._new_pointer_at(
ctypes.addressof(self._blob) +
other * ctypes.sizeof(BItem._ctype))
@@ -658,7 +676,7 @@
"only one supported (use a dict if needed)"
% (len(init),))
if not isinstance(init, dict):
- if isinstance(init, str):
+ if isinstance(init, (bytes, str)):
raise TypeError("union initializer: got a str")
init = tuple(init)
if len(init) > len(fnames):
@@ -675,7 +693,7 @@
p = ctypes.cast(addr + offset, PTR)
BField._initialize(p.contents, value)
is_union = CTypesStructOrUnion._kind == 'union'
- name2fieldtype = dict(zip(fnames, zip(btypes, bitfields)))
+ name2fieldtype = dict(zip(fnames, list(zip(btypes, bitfields))))
#
for fname, BField, bitsize in fields:
if hasattr(CTypesStructOrUnion, fname):
@@ -819,7 +837,8 @@
def new_enum_type(self, name, enumerators, enumvalues):
assert isinstance(name, str)
mapping = dict(zip(enumerators, enumvalues))
- reverse_mapping = dict(reversed(zip(enumvalues, enumerators)))
+ reverse_mapping = dict(zip(reversed(enumvalues),
+ reversed(enumerators)))
CTypesInt = self.ffi._get_cached_btype(model.PrimitiveType('int'))
#
def forward_map(source):
@@ -871,6 +890,26 @@
ctypes.set_errno(value)
def buffer(self, bptr, size=-1):
+ if sys.version >= '3':
+ # buf = bptr._as_ctype_ptr
+ # return memoryview(buf.contents)
+ if isinstance(bptr, CTypesGenericPtr):
+ buf = bptr._as_ctype_ptr
+ val = buf.contents
+ elif isinstance(bptr, CTypesGenericArray):
+ buf = bptr._blob
+ val = bptr._blob
+ else:
+ buf = bptr.XXX
+ class Hack(ctypes.Union):
+ _fields_ = [('stupid', type(val))]
+ ptr = ctypes.cast(buf, ctypes.POINTER(Hack))
+ view = memoryview(ptr.contents)
+ if size >= 0:
+ return view.cast('B')[:size]
+ else:
+ return view.cast('B')
+
# haaaaaaaaaaaack
call = ctypes.pythonapi.PyBuffer_FromReadWriteMemory
call.argtypes = (ctypes.c_void_p, ctypes.c_size_t)
diff --git a/cffi/ffiplatform.py b/cffi/ffiplatform.py
--- a/cffi/ffiplatform.py
+++ b/cffi/ffiplatform.py
@@ -54,7 +54,7 @@
try:
dist.run_command('build_ext')
except (distutils.errors.CompileError,
- distutils.errors.LinkError), e:
+ distutils.errors.LinkError) as e:
raise VerificationError('%s: %s' % (e.__class__.__name__, e))
#
cmd_obj = dist.get_command_obj('build_ext')
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -182,7 +182,7 @@
fldtypes = tuple(ffi._get_cached_btype(tp) for tp in self.fldtypes)
#
if self.fixedlayout is None:
- lst = zip(self.fldnames, fldtypes, self.fldbitsize)
+ lst = list(zip(self.fldnames, fldtypes, self.fldbitsize))
ffi._backend.complete_struct_or_union(BType, lst, self)
#
else:
@@ -213,7 +213,7 @@
"field '%s.%s' is declared as %d bytes, but is "
"really %d bytes" % (self.name, self.fldnames[i],
bitemsize, fsize))
- lst = zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)
+ lst = list(zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs))
ffi._backend.complete_struct_or_union(BType, lst, self,
totalsize, totalalignment)
return BType
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
import sys, os, hashlib, imp, shutil
from . import model, ffiplatform
from . import __version__
@@ -17,7 +18,7 @@
self.kwds = kwds
#
m = hashlib.md5('\x00'.join([sys.version[:3], __version__, preamble] +
- ffi._cdefsources))
+ ffi._cdefsources).encode())
modulename = '_cffi_%s' % m.hexdigest()
suffix = _get_so_suffix()
self.sourcefilename = os.path.join(_TMPDIR, modulename + '.c')
@@ -59,7 +60,7 @@
return self._load_library()
def get_module_name(self):
- return os.path.splitext(os.path.basename(self.modulefilename))[0]
+ return os.path.basename(self.modulefilename).split('.', 1)[0]
def get_extension(self):
if self._status == 'init':
@@ -82,8 +83,8 @@
self._collect_types()
self._status = 'module'
- def _prnt(self, what=''):
- print >> self._f, what
+ def print(self, what=''):
+ print(what, file=self._f)
def _gettypenum(self, type):
# a KeyError here is a bug. please report it! :-)
@@ -133,13 +134,13 @@
# call to do, if any.
self._chained_list_constants = ['0', '0']
#
- prnt = self._prnt
+ print = self.print
# first paste some standard set of lines that are mostly '#define'
- prnt(cffimod_header)
- prnt()
+ print(cffimod_header)
+ print()
# then paste the C source given by the user, verbatim.
- prnt(self.preamble)
- prnt()
+ print(self.preamble)
+ print()
#
# call generate_cpy_xxx_decl(), for every xxx found from
# ffi._parser._declarations. This generates all the functions.
@@ -148,30 +149,52 @@
# implement the function _cffi_setup_custom() as calling the
# head of the chained list.
self._generate_setup_custom()
- prnt()
+ print()
#
# produce the method table, including the entries for the
# generated Python->C function wrappers, which are done
# by generate_cpy_function_method().
- prnt('static PyMethodDef _cffi_methods[] = {')
+ print('static PyMethodDef _cffi_methods[] = {')
self._generate("method")
- prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS},')
- prnt(' {NULL, NULL} /* Sentinel */')
- prnt('};')
- prnt()
+ print(' {"_cffi_setup", _cffi_setup, METH_VARARGS},')
+ print(' {NULL, NULL} /* Sentinel */')
+ print('};')
+ print()
#
# standard init.
modname = self.get_module_name()
- prnt('PyMODINIT_FUNC')
- prnt('init%s(void)' % modname)
- prnt('{')
- prnt(' PyObject *lib;')
- prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname)
- prnt(' if (lib == NULL || %s < 0)' % (
- self._chained_list_constants[False],))
- prnt(' return;')
- prnt(' _cffi_init();')
- prnt('}')
+ if sys.version < '3':
+ print('PyMODINIT_FUNC')
+ print('init%s(void)' % modname)
+ print('{')
+ print(' PyObject *lib;')
+ print(' lib = Py_InitModule("%s", _cffi_methods);' % modname)
+ print(' if (lib == NULL || %s < 0)' % (
+ self._chained_list_constants[False],))
+ print(' return;')
+ print(' _cffi_init();')
+ print('}')
+ else:
+ print('static struct PyModuleDef _cffi_module_def = {')
+ print(' PyModuleDef_HEAD_INIT,')
+ print(' "%s",' % modname)
+ print(' NULL,')
+ print(' -1,')
+ print(' _cffi_methods,')
+ print(' NULL, NULL, NULL, NULL')
+ print('};')
+ print('')
+ print('PyMODINIT_FUNC')
+ print('PyInit_%s(void)' % modname)
+ print('{')
+ print(' PyObject *lib;')
+ print(' lib = PyModule_Create(&_cffi_module_def);')
+ print(' if (lib == NULL || %s < 0)' % (
+ self._chained_list_constants[False],))
+ print(' return NULL;')
+ print(' _cffi_init();')
+ print(' return lib;')
+ print('}')
def _compile_module(self):
# compile this C source
@@ -192,7 +215,7 @@
try:
module = imp.load_dynamic(self.get_module_name(),
self.modulefilename)
- except ImportError, e:
+ except ImportError as e:
error = "importing %r: %s" % (self.modulefilename, e)
raise ffiplatform.VerificationError(error)
#
@@ -205,7 +228,7 @@
revmapping = dict([(value, key)
for (key, value) in self._typesdict.items()])
lst = [revmapping[i] for i in range(len(revmapping))]
- lst = map(self.ffi._get_cached_btype, lst)
+ lst = list(map(self.ffi._get_cached_btype, lst))
#
# build the FFILibrary class and instance and call _cffi_setup().
# this will set up some fields like '_cffi_types', and only then
@@ -225,7 +248,7 @@
return library
def _generate(self, step_name):
- for name, tp in self.ffi._parser._declarations.iteritems():
+ for name, tp in self.ffi._parser._declarations.items():
kind, realname = name.split(' ', 1)
try:
method = getattr(self, '_generate_cpy_%s_%s' % (kind,
@@ -236,7 +259,7 @@
method(tp, realname)
def _load(self, module, step_name, **kwds):
- for name, tp in self.ffi._parser._declarations.iteritems():
+ for name, tp in self.ffi._parser._declarations.items():
kind, realname = name.split(' ', 1)
method = getattr(self, '_%s_cpy_%s' % (step_name, kind))
method(tp, realname, module, **kwds)
@@ -266,9 +289,9 @@
#
elif isinstance(tp, (model.StructOrUnion, model.EnumType)):
# a struct (not a struct pointer) as a function argument
- self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
+ self.print(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
% (tovar, self._gettypenum(tp), fromvar))
- self._prnt(' %s;' % errcode)
+ self.print(' %s;' % errcode)
return
#
elif isinstance(tp, model.FunctionPtrType):
@@ -279,10 +302,10 @@
else:
raise NotImplementedError(tp)
#
- self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg))
- self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % (
+ self.print(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg))
+ self.print(' if (%s == (%s)%s && PyErr_Occurred())' % (
tovar, tp.get_c_name(''), errvalue))
- self._prnt(' %s;' % errcode)
+ self.print(' %s;' % errcode)
def _convert_expr_from_c(self, tp, var):
if isinstance(tp, model.PrimitiveType):
@@ -331,7 +354,7 @@
# constant function pointer (no CPython wrapper)
self._generate_cpy_const(False, name, tp)
return
- prnt = self._prnt
+ print = self.print
numargs = len(tp.args)
if numargs == 0:
argname = 'no_arg'
@@ -339,48 +362,48 @@
argname = 'arg0'
else:
argname = 'args'
- prnt('static PyObject *')
- prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
- prnt('{')
+ print('static PyObject *')
+ print('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
+ print('{')
#
for i, type in enumerate(tp.args):
- prnt(' %s;' % type.get_c_name(' x%d' % i))
+ print(' %s;' % type.get_c_name(' x%d' % i))
if not isinstance(tp.result, model.VoidType):
result_code = 'result = '
- prnt(' %s;' % tp.result.get_c_name(' result'))
+ print(' %s;' % tp.result.get_c_name(' result'))
else:
result_code = ''
#
if len(tp.args) > 1:
rng = range(len(tp.args))
for i in rng:
- prnt(' PyObject *arg%d;' % i)
- prnt()
- prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % (
+ print(' PyObject *arg%d;' % i)
+ print()
+ print(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % (
'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng])))
- prnt(' return NULL;')
- prnt()
+ print(' return NULL;')
+ print()
#
for i, type in enumerate(tp.args):
self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i,
'return NULL')
- prnt()
+ print()
#
- prnt(' _cffi_restore_errno();')
- prnt(' { %s%s(%s); }' % (
+ print(' _cffi_restore_errno();')
+ print(' { %s%s(%s); }' % (
result_code, name,
', '.join(['x%d' % i for i in range(len(tp.args))])))
- prnt(' _cffi_save_errno();')
- prnt()
+ print(' _cffi_save_errno();')
+ print()
#
if result_code:
- prnt(' return %s;' %
+ print(' return %s;' %
self._convert_expr_from_c(tp.result, 'result'))
else:
- prnt(' Py_INCREF(Py_None);')
- prnt(' return Py_None;')
- prnt('}')
- prnt()
+ print(' Py_INCREF(Py_None);')
+ print(' return Py_None;')
+ print('}')
+ print()
def _generate_cpy_function_method(self, tp, name):
if tp.ellipsis:
@@ -392,7 +415,7 @@
meth = 'METH_O'
else:
meth = 'METH_VARARGS'
- self._prnt(' {"%s", _cffi_f_%s, %s},' % (name, name, meth))
+ self.print(' {"%s", _cffi_f_%s, %s},' % (name, name, meth))
_loading_cpy_function = _loaded_noop
@@ -426,38 +449,38 @@
layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
cname = ('%s %s' % (prefix, name)).strip()
#
- prnt = self._prnt
- prnt('static void %s(%s *p)' % (checkfuncname, cname))
- prnt('{')
- prnt(' /* only to generate compile-time warnings or errors */')
+ print = self.print
+ print('static void %s(%s *p)' % (checkfuncname, cname))
+ print('{')
+ print(' /* only to generate compile-time warnings or errors */')
for i in range(len(tp.fldnames)):
fname = tp.fldnames[i]
ftype = tp.fldtypes[i]
if (isinstance(ftype, model.PrimitiveType)
and ftype.is_integer_type()):
# accept all integers, but complain on float or double
- prnt(' (void)((p->%s) << 1);' % fname)
+ print(' (void)((p->%s) << 1);' % fname)
else:
# only accept exactly the type declared. Note the parentheses
# around the '*tmp' below. In most cases they are not needed
# but don't hurt --- except test_struct_array_field.
- prnt(' { %s = &p->%s; (void)tmp; }' % (
+ print(' { %s = &p->%s; (void)tmp; }' % (
ftype.get_c_name('(*tmp)'), fname))
- prnt('}')
- prnt('static PyObject *')
- prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,))
- prnt('{')
- prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname)
+ print('}')
+ print('static PyObject *')
+ print('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,))
+ print('{')
+ print(' struct _cffi_aligncheck { char x; %s y; };' % cname)
if tp.partial:
- prnt(' static Py_ssize_t nums[] = {')
- prnt(' sizeof(%s),' % cname)
- prnt(' offsetof(struct _cffi_aligncheck, y),')
+ print(' static Py_ssize_t nums[] = {')
+ print(' sizeof(%s),' % cname)
+ print(' offsetof(struct _cffi_aligncheck, y),')
for fname in tp.fldnames:
- prnt(' offsetof(%s, %s),' % (cname, fname))
- prnt(' sizeof(((%s *)0)->%s),' % (cname, fname))
- prnt(' -1')
- prnt(' };')
- prnt(' return _cffi_get_struct_layout(nums);')
+ print(' offsetof(%s, %s),' % (cname, fname))
+ print(' sizeof(((%s *)0)->%s),' % (cname, fname))
+ print(' -1')
+ print(' };')
+ print(' return _cffi_get_struct_layout(nums);')
else:
ffi = self.ffi
BStruct = ffi._get_cached_btype(tp)
@@ -472,27 +495,27 @@
cname, fname, ffi.offsetof(BStruct, fname)),
'sizeof(((%s *)0)->%s) != %d' % (
cname, fname, ffi.sizeof(BField))]
- prnt(' if (%s ||' % conditions[0])
+ print(' if (%s ||' % conditions[0])
for i in range(1, len(conditions)-1):
- prnt(' %s ||' % conditions[i])
- prnt(' %s) {' % conditions[-1])
- prnt(' Py_INCREF(Py_False);')
- prnt(' return Py_False;')
- prnt(' }')
- prnt(' else {')
- prnt(' Py_INCREF(Py_True);')
- prnt(' return Py_True;')
- prnt(' }')
- prnt(' /* the next line is not executed, but compiled */')
- prnt(' %s(0);' % (checkfuncname,))
- prnt('}')
- prnt()
+ print(' %s ||' % conditions[i])
+ print(' %s) {' % conditions[-1])
+ print(' Py_INCREF(Py_False);')
+ print(' return Py_False;')
+ print(' }')
+ print(' else {')
+ print(' Py_INCREF(Py_True);')
+ print(' return Py_True;')
+ print(' }')
+ print(' /* the next line is not executed, but compiled */')
+ print(' %s(0);' % (checkfuncname,))
+ print('}')
+ print()
def _generate_struct_or_union_method(self, tp, prefix, name):
if tp.fldnames is None:
return # nothing to do with opaque structs
layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
- self._prnt(' {"%s", %s, METH_NOARGS},' % (layoutfuncname,
+ self.print(' {"%s", %s, METH_NOARGS},' % (layoutfuncname,
layoutfuncname))
def _loading_struct_or_union(self, tp, prefix, name, module):
@@ -544,14 +567,14 @@
def _generate_cpy_const(self, is_int, name, tp=None, category='const',
vartp=None, delayed=True):
- prnt = self._prnt
+ print = self.print
funcname = '_cffi_%s_%s' % (category, name)
- prnt('static int %s(PyObject *lib)' % funcname)
- prnt('{')
- prnt(' PyObject *o;')
- prnt(' int res;')
+ print('static int %s(PyObject *lib)' % funcname)
+ print('{')
+ print(' PyObject *o;')
+ print(' int res;')
if not is_int:
- prnt(' %s;' % (vartp or tp).get_c_name(' i'))
+ print(' %s;' % (vartp or tp).get_c_name(' i'))
else:
assert category == 'const'
#
@@ -560,27 +583,27 @@
realexpr = '&' + name
else:
realexpr = name
- prnt(' i = (%s);' % (realexpr,))
- prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i'),))
+ print(' i = (%s);' % (realexpr,))
+ print(' o = %s;' % (self._convert_expr_from_c(tp, 'i'),))
assert delayed
else:
- prnt(' if (LONG_MIN <= (%s) && (%s) <= LONG_MAX)' % (name, name))
- prnt(' o = PyInt_FromLong((long)(%s));' % (name,))
- prnt(' else if ((%s) <= 0)' % (name,))
- prnt(' o = PyLong_FromLongLong((long long)(%s));' % (name,))
- prnt(' else')
- prnt(' o = PyLong_FromUnsignedLongLong('
+ print(' if (LONG_MIN <= (%s) && (%s) <= LONG_MAX)' % (name, name))
+ print(' o = PyInt_FromLong((long)(%s));' % (name,))
+ print(' else if ((%s) <= 0)' % (name,))
+ print(' o = PyLong_FromLongLong((long long)(%s));' % (name,))
+ print(' else')
+ print(' o = PyLong_FromUnsignedLongLong('
'(unsigned long long)(%s));' % (name,))
- prnt(' if (o == NULL)')
- prnt(' return -1;')
- prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name)
- prnt(' Py_DECREF(o);')
- prnt(' if (res < 0)')
- prnt(' return -1;')
- prnt(' return %s;' % self._chained_list_constants[delayed])
+ print(' if (o == NULL)')
+ print(' return -1;')
+ print(' res = PyObject_SetAttrString(lib, "%s", o);' % name)
+ print(' Py_DECREF(o);')
+ print(' if (res < 0)')
+ print(' return -1;')
+ print(' return %s;' % self._chained_list_constants[delayed])
self._chained_list_constants[delayed] = funcname + '(lib)'
- prnt('}')
- prnt()
+ print('}')
+ print()
def _generate_cpy_constant_collecttype(self, tp, name):
is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
@@ -605,22 +628,22 @@
return
#
funcname = '_cffi_enum_%s' % name
- prnt = self._prnt
- prnt('static int %s(PyObject *lib)' % funcname)
- prnt('{')
+ print = self.print
+ print('static int %s(PyObject *lib)' % funcname)
+ print('{')
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, '
+ print(' if (%s != %d) {' % (enumerator, enumvalue))
+ print(' PyErr_Format(_cffi_VerificationError,')
+ print(' "in enum %s: %s has the real value %d, '
'not %d",')
- prnt(' "%s", "%s", (int)%s, %d);' % (
+ print(' "%s", "%s", (int)%s, %d);' % (
name, enumerator, enumerator, enumvalue))
- prnt(' return -1;')
- prnt(' }')
- prnt(' return %s;' % self._chained_list_constants[True])
+ print(' return -1;')
+ print(' }')
+ print(' return %s;' % self._chained_list_constants[True])
self._chained_list_constants[True] = funcname + '(lib)'
- prnt('}')
- prnt()
+ print('}')
+ print()
_generate_cpy_enum_collecttype = _generate_nothing
_generate_cpy_enum_method = _generate_nothing
@@ -686,19 +709,30 @@
# ----------
def _generate_setup_custom(self):
- prnt = self._prnt
- prnt('static PyObject *_cffi_setup_custom(PyObject *lib)')
- prnt('{')
- prnt(' if (%s < 0)' % self._chained_list_constants[True])
- prnt(' return NULL;')
- prnt(' Py_INCREF(Py_None);')
- prnt(' return Py_None;')
- prnt('}')
+ print = self.print
+ print('static PyObject *_cffi_setup_custom(PyObject *lib)')
+ print('{')
+ print(' if (%s < 0)' % self._chained_list_constants[True])
+ print(' return NULL;')
+ print(' Py_INCREF(Py_None);')
+ print(' return Py_None;')
+ print('}')
cffimod_header = r'''
#include <Python.h>
#include <stddef.h>
+#if PY_MAJOR_VERSION < 3
+# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
+# define PyCapsule_GetPointer(capsule, name) \
+ (PyCObject_AsVoidPtr(capsule))
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+# define PyInt_FromLong PyLong_FromLong
+# define PyInt_AsLong PyLong_AsLong
+#endif
+
#define _cffi_from_c_double PyFloat_FromDouble
#define _cffi_from_c_float PyFloat_FromDouble
#define _cffi_from_c_signed_char PyInt_FromLong
@@ -812,11 +846,11 @@
c_api_object = PyObject_GetAttrString(module, "_C_API");
if (c_api_object == NULL)
return;
- if (!PyCObject_Check(c_api_object)) {
+ if (!PyCapsule_CheckExact(c_api_object)) {
PyErr_SetNone(PyExc_ImportError);
return;
}
- memcpy(_cffi_exports, PyCObject_AsVoidPtr(c_api_object),
+ memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"),
_CFFI_NUM_EXPORTS * sizeof(void *));
}
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -16,11 +16,11 @@
try:
p = subprocess.Popen(['pkg-config', option, 'libffi'],
stdout=subprocess.PIPE, stderr=open('/dev/null', 'w'))
- except OSError, e:
+ except OSError as e:
if e.errno != errno.ENOENT:
raise
else:
- t = p.stdout.read().strip()
+ t = p.stdout.read().decode().strip()
if p.wait() == 0:
res = t.split()
# '-I/usr/...' -> '/usr/...'
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -57,24 +57,26 @@
assert int(p) == min
p = ffi.cast(c_decl, max)
assert int(p) == max
- p = ffi.cast(c_decl, long(max))
- assert int(p) == max
q = ffi.cast(c_decl, min - 1)
assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
- q = ffi.cast(c_decl, long(min - 1))
- assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
+ if sys.version < '3':
+ p = ffi.cast(c_decl, long(max))
+ assert int(p) == max
+ q = ffi.cast(c_decl, long(min - 1))
+ assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
assert q != p
assert int(q) == int(p)
assert hash(q) != hash(p) # unlikely
c_decl_ptr = '%s *' % c_decl
py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
- py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
- py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
assert ffi.new(c_decl_ptr, min)[0] == min
assert ffi.new(c_decl_ptr, max)[0] == max
- assert ffi.new(c_decl_ptr, long(min))[0] == min
- assert ffi.new(c_decl_ptr, long(max))[0] == max
+ if sys.version < '3':
+ py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
+ py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
+ assert ffi.new(c_decl_ptr, long(min))[0] == min
+ assert ffi.new(c_decl_ptr, long(max))[0] == max
def test_new_unsupported_type(self):
ffi = FFI(backend=self.Backend())
@@ -276,32 +278,35 @@
def test_char(self):
ffi = FFI(backend=self.Backend())
- assert ffi.new("char*", "\xff")[0] == '\xff'
- assert ffi.new("char*")[0] == '\x00'
+ assert ffi.new("char*", b"\xff")[0] == b'\xff'
+ assert ffi.new("char*")[0] == b'\x00'
assert int(ffi.cast("char", 300)) == 300 - 256
assert bool(ffi.cast("char", 0))
- py.test.raises(TypeError, ffi.new, "char*", 32)
+ if sys.version < '3':
+ py.test.raises(TypeError, ffi.new, "char*", 32)
+ else:
+ assert ffi.new("char*", 32)[0] == b' '
py.test.raises(TypeError, ffi.new, "char*", u"x")
py.test.raises(TypeError, ffi.new, "char*", "foo")
#
- p = ffi.new("char[]", ['a', 'b', '\x9c'])
+ p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
assert len(p) == 3
- assert p[0] == 'a'
- assert p[1] == 'b'
- assert p[2] == '\x9c'
- p[0] = '\xff'
- assert p[0] == '\xff'
- p = ffi.new("char[]", "abcd")
+ assert p[0] == b'a'
+ assert p[1] == b'b'
+ assert p[2] == b'\x9c'
+ p[0] = b'\xff'
+ assert p[0] == b'\xff'
+ p = ffi.new("char[]", b"abcd")
assert len(p) == 5
- assert p[4] == '\x00' # like in C, with: char[] p = "abcd";
+ assert p[4] == b'\x00' # like in C, with: char[] p = "abcd";
#
- p = ffi.new("char[4]", "ab")
+ p = ffi.new("char[4]", b"ab")
assert len(p) == 4
- assert [p[i] for i in range(4)] == ['a', 'b', '\x00', '\x00']
- p = ffi.new("char[2]", "ab")
+ assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
+ p = ffi.new("char[2]", b"ab")
assert len(p) == 2
- assert [p[i] for i in range(2)] == ['a', 'b']
- py.test.raises(IndexError, ffi.new, "char[2]", "abc")
+ assert [p[i] for i in range(2)] == [b'a', b'b']
+ py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
def check_wchar_t(self, ffi):
try:
@@ -313,7 +318,7 @@
ffi = FFI(backend=self.Backend())
self.check_wchar_t(ffi)
assert ffi.new("wchar_t*", u'x')[0] == u'x'
- assert ffi.new("wchar_t*", unichr(1234))[0] == unichr(1234)
+ assert ffi.new("wchar_t*", u'\u1234')[0] == u'\u1234'
if SIZE_OF_WCHAR > 2:
assert ffi.new("wchar_t*", u'\U00012345')[0] == u'\U00012345'
else:
@@ -324,21 +329,21 @@
py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
#
- p = ffi.new("wchar_t[]", [u'a', u'b', unichr(1234)])
+ p = ffi.new("wchar_t[]", [u'a', u'b', u'\u1234'])
assert len(p) == 3
assert p[0] == u'a'
- assert p[1] == u'b' and type(p[1]) is unicode
- assert p[2] == unichr(1234)
+ assert p[1] == u'b' and type(p[1]) is type(u'')
+ assert p[2] == u'\u1234'
p[0] = u'x'
- assert p[0] == u'x' and type(p[0]) is unicode
- p[1] = unichr(1357)
- assert p[1] == unichr(1357)
+ assert p[0] == u'x' and type(p[0]) is type(u'')
+ p[1] = u'\u1357'
+ assert p[1] == u'\u1357'
p = ffi.new("wchar_t[]", u"abcd")
assert len(p) == 5
assert p[4] == u'\x00'
p = ffi.new("wchar_t[]", u"a\u1234b")
assert len(p) == 4
- assert p[1] == unichr(0x1234)
+ assert p[1] == u'\u1234'
#
p = ffi.new("wchar_t[]", u'\U00023456')
if SIZE_OF_WCHAR == 2:
@@ -469,13 +474,13 @@
def test_constructor_struct_of_array(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a[2]; char b[3]; };")
- s = ffi.new("struct foo *", [[10, 11], ['a', 'b', 'c']])
+ s = ffi.new("struct foo *", [[10, 11], [b'a', b'b', b'c']])
assert s.a[1] == 11
- assert s.b[2] == 'c'
- s.b[1] = 'X'
- assert s.b[0] == 'a'
- assert s.b[1] == 'X'
- assert s.b[2] == 'c'
+ assert s.b[2] == b'c'
+ s.b[1] = b'X'
+ assert s.b[0] == b'a'
+ assert s.b[1] == b'X'
+ assert s.b[2] == b'c'
def test_recursive_struct(self):
ffi = FFI(backend=self.Backend())
@@ -512,16 +517,16 @@
def test_union_initializer(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("union foo { char a; int b; };")
- py.test.raises(TypeError, ffi.new, "union foo*", 'A')
+ py.test.raises(TypeError, ffi.new, "union foo*", b'A')
py.test.raises(TypeError, ffi.new, "union foo*", 5)
- py.test.raises(ValueError, ffi.new, "union foo*", ['A', 5])
- u = ffi.new("union foo*", ['A'])
- assert u.a == 'A'
- py.test.raises(TypeError, ffi.new, "union foo*", [5])
+ py.test.raises(ValueError, ffi.new, "union foo*", [b'A', 5])
+ u = ffi.new("union foo*", [b'A'])
+ assert u.a == b'A'
+ py.test.raises(TypeError, ffi.new, "union foo*", [1005])
u = ffi.new("union foo*", {'b': 12345})
assert u.b == 12345
u = ffi.new("union foo*", [])
- assert u.a == '\x00'
+ assert u.a == b'\x00'
assert u.b == 0
def test_sizeof_type(self):
@@ -552,64 +557,64 @@
def test_str_from_char_pointer(self):
ffi = FFI(backend=self.Backend())
- assert str(ffi.new("char*", "x")) == "x"
- assert str(ffi.new("char*", "\x00")) == ""
+ assert ffi.new("char*", b"x").value == b"x"
+ assert ffi.new("char*", b"\x00").value == b""
def test_unicode_from_wchar_pointer(self):
ffi = FFI(backend=self.Backend())
self.check_wchar_t(ffi)
- assert unicode(ffi.new("wchar_t*", u"x")) == u"x"
- assert unicode(ffi.new("wchar_t*", u"\x00")) == u""
+ assert ffi.new("wchar_t*", u"x").value == u"x"
+ assert ffi.new("wchar_t*", u"\x00").value == u""
x = ffi.new("wchar_t*", u"\x00")
assert str(x) == repr(x)
def test_string_from_char_array(self):
ffi = FFI(backend=self.Backend())
- assert str(ffi.cast("char", "x")) == "x"
- p = ffi.new("char[]", "hello.")
- p[5] = '!'
- assert str(p) == "hello!"
- p[6] = '?'
- assert str(p) == "hello!?"
- p[3] = '\x00'
- assert str(p) == "hel"
- py.test.raises(IndexError, "p[7] = 'X'")
+ assert ffi.cast("char", b"x").value == b"x"
+ p = ffi.new("char[]", b"hello.")
+ p[5] = b'!'
+ assert p.value == b"hello!"
+ p[6] = b'?'
+ assert p.value == b"hello!?"
+ p[3] = b'\x00'
+ assert p.value == b"hel"
+ py.test.raises(IndexError, "p[7] = b'X'")
#
- a = ffi.new("char[]", "hello\x00world")
+ a = ffi.new("char[]", b"hello\x00world")
assert len(a) == 12
p = ffi.cast("char *", a)
- assert str(p) == 'hello'
+ assert p.value == b'hello'
def test_string_from_wchar_array(self):
ffi = FFI(backend=self.Backend())
self.check_wchar_t(ffi)
- assert unicode(ffi.cast("wchar_t", "x")) == u"x"
- assert unicode(ffi.cast("wchar_t", u"x")) == u"x"
+ assert ffi.cast("wchar_t", b"x").value == u"x"
+ assert ffi.cast("wchar_t", u"x").value == u"x"
x = ffi.cast("wchar_t", "x")
assert str(x) == repr(x)
#
p = ffi.new("wchar_t[]", u"hello.")
p[5] = u'!'
- assert unicode(p) == u"hello!"
- p[6] = unichr(1234)
- assert unicode(p) == u"hello!\u04d2"
+ assert p.value == u"hello!"
+ p[6] = u'\u1234'
+ assert p.value == u"hello!\u1234"
p[3] = u'\x00'
- assert unicode(p) == u"hel"
+ assert p.value == u"hel"
py.test.raises(IndexError, "p[7] = u'X'")
#
a = ffi.new("wchar_t[]", u"hello\x00world")
assert len(a) == 12
p = ffi.cast("wchar_t *", a)
- assert unicode(p) == u'hello'
+ assert p.value == u'hello'
def test_fetch_const_char_p_field(self):
# 'const' is ignored so far
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { const char *name; };")
- t = ffi.new("const char[]", "testing")
+ t = ffi.new("const char[]", b"testing")
s = ffi.new("struct foo*", [t])
assert type(s.name) is not str
- assert str(s.name) == "testing"
+ assert s.name.value == b"testing"
py.test.raises(TypeError, "s.name = None")
s.name = ffi.NULL
assert s.name == ffi.NULL
@@ -621,8 +626,11 @@
ffi.cdef("struct foo { const wchar_t *name; };")
t = ffi.new("const wchar_t[]", u"testing")
s = ffi.new("struct foo*", [t])
- assert type(s.name) not in (str, unicode)
- assert unicode(s.name) == u"testing"
+ if sys.version < '3':
+ assert type(s.name) not in (str, unicode)
+ else:
+ assert type(s.name) not in (bytes, str)
+ assert s.name.value == u"testing"
s.name = ffi.NULL
assert s.name == ffi.NULL
@@ -653,6 +661,7 @@
py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
def cb(n):
return n + 1
+ cb.__qualname__ = 'cb'
p = ffi.callback("int(*)(int)", cb)
res = p(41) # calling an 'int(*)(int)', i.e. a function pointer
assert res == 42 and type(res) is int
@@ -725,38 +734,38 @@
def test_char_cast(self):
ffi = FFI(backend=self.Backend())
- p = ffi.cast("int", '\x01')
+ p = ffi.cast("int", b'\x01')
assert ffi.typeof(p) is ffi.typeof("int")
assert int(p) == 1
- p = ffi.cast("int", ffi.cast("char", "a"))
+ p = ffi.cast("int", ffi.cast("char", b"a"))
assert int(p) == ord("a")
- p = ffi.cast("int", ffi.cast("char", "\x80"))
+ p = ffi.cast("int", ffi.cast("char", b"\x80"))
assert int(p) == 0x80 # "char" is considered unsigned in this case
- p = ffi.cast("int", "\x81")
+ p = ffi.cast("int", b"\x81")
assert int(p) == 0x81
def test_wchar_cast(self):
ffi = FFI(backend=self.Backend())
self.check_wchar_t(ffi)
- p = ffi.cast("int", ffi.cast("wchar_t", unichr(1234)))
- assert int(p) == 1234
+ p = ffi.cast("int", ffi.cast("wchar_t", u'\u1234'))
+ assert int(p) == 0x1234
p = ffi.cast("long long", ffi.cast("wchar_t", -1))
if SIZE_OF_WCHAR == 2: # 2 bytes, unsigned
assert int(p) == 0xffff
else: # 4 bytes, signed
assert int(p) == -1
- p = ffi.cast("int", unichr(1234))
- assert int(p) == 1234
+ p = ffi.cast("int", u'\u1234')
+ assert int(p) == 0x1234
def test_cast_array_to_charp(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("short int[]", [0x1234, 0x5678])
p = ffi.cast("char*", a)
- data = ''.join([p[i] for i in range(4)])
+ data = b''.join([p[i] for i in range(4)])
if sys.byteorder == 'little':
- assert data == '\x34\x12\x78\x56'
+ assert data == b'\x34\x12\x78\x56'
else:
- assert data == '\x12\x34\x56\x78'
+ assert data == b'\x12\x34\x56\x78'
def test_cast_between_pointers(self):
ffi = FFI(backend=self.Backend())
@@ -764,11 +773,11 @@
p = ffi.cast("short*", a)
p2 = ffi.cast("int*", p)
q = ffi.cast("char*", p2)
- data = ''.join([q[i] for i in range(4)])
+ data = b''.join([q[i] for i in range(4)])
if sys.byteorder == 'little':
- assert data == '\x34\x12\x78\x56'
+ assert data == b'\x34\x12\x78\x56'
else:
- assert data == '\x12\x34\x56\x78'
+ assert data == b'\x12\x34\x56\x78'
def test_cast_pointer_and_int(self):
ffi = FFI(backend=self.Backend())
@@ -808,23 +817,23 @@
assert float(a) == 12.0
a = ffi.cast("float", 12.5)
assert float(a) == 12.5
- a = ffi.cast("float", "A")
+ a = ffi.cast("float", b"A")
assert float(a) == ord("A")
a = ffi.cast("int", 12.9)
assert int(a) == 12
a = ffi.cast("char", 66.9 + 256)
- assert str(a) == "B"
+ assert a.value == b"B"
#
a = ffi.cast("float", ffi.cast("int", 12))
assert float(a) == 12.0
a = ffi.cast("float", ffi.cast("double", 12.5))
assert float(a) == 12.5
- a = ffi.cast("float", ffi.cast("char", "A"))
+ a = ffi.cast("float", ffi.cast("char", b"A"))
assert float(a) == ord("A")
a = ffi.cast("int", ffi.cast("double", 12.9))
assert int(a) == 12
a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
- assert str(a) == "B"
+ assert a.value == b"B"
def test_enum(self):
ffi = FFI(backend=self.Backend())
@@ -891,9 +900,9 @@
def test_iterate_array(self):
ffi = FFI(backend=self.Backend())
- a = ffi.new("char[]", "hello")
- assert list(a) == ["h", "e", "l", "l", "o", chr(0)]
- assert list(iter(a)) == ["h", "e", "l", "l", "o", chr(0)]
+ a = ffi.new("char[]", b"hello")
+ assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
+ assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
#
py.test.raises(TypeError, iter, ffi.cast("char *", a))
py.test.raises(TypeError, list, ffi.cast("char *", a))
@@ -939,10 +948,10 @@
ffi.cdef("typedef struct { int a; } foo_t;")
ffi.cdef("typedef struct { char b, c; } bar_t;")
f = ffi.new("foo_t *", [12345])
- b = ffi.new("bar_t *", ["B", "C"])
+ b = ffi.new("bar_t *", [b"B", b"C"])
assert f.a == 12345
- assert b.b == "B"
- assert b.c == "C"
+ assert b.b == b"B"
+ assert b.c == b"C"
assert repr(b).startswith("<cdata 'struct $bar_t *'")
def test_struct_with_two_usages(self):
@@ -954,7 +963,7 @@
def test_pointer_arithmetic(self):
ffi = FFI(backend=self.Backend())
- s = ffi.new("short[]", range(100, 110))
+ s = ffi.new("short[]", list(range(100, 110)))
p = ffi.cast("short *", s)
assert p[2] == 102
assert p+1 == p+1
@@ -968,7 +977,7 @@
def test_pointer_comparison(self):
ffi = FFI(backend=self.Backend())
- s = ffi.new("short[]", range(100))
+ s = ffi.new("short[]", list(range(100)))
p = ffi.cast("short *", s)
assert (p < s) is False
assert (p <= s) is True
@@ -1031,57 +1040,75 @@
ffi = FFI(backend=self.Backend())
a = ffi.new("short *", 100)
b = ffi.buffer(a)
- assert type(b) is buffer
- assert len(str(b)) == 2
+ if sys.version < '3':
+ assert type(b) is buffer
+ content = str(b)
+ else:
+ assert type(b) is memoryview
+ content = b.tobytes()
+ assert len(content) == 2
if sys.byteorder == 'little':
- assert str(b) == '\x64\x00'
- b[0] = '\x65'
+ assert content == b'\x64\x00'
+ b[0] = b'\x65'[0]
else:
- assert str(b) == '\x00\x64'
- b[1] = '\x65'
+ assert content == b'\x00\x64'
+ b[1] = b'\x65'[0]
assert a[0] == 101
def test_ffi_buffer_array(self):
ffi = FFI(backend=self.Backend())
- a = ffi.new("int[]", range(100, 110))
+ a = ffi.new("int[]", list(range(100, 110)))
b = ffi.buffer(a)
- assert type(b) is buffer
+ if sys.version < '3':
+ assert type(b) is buffer
+ content = str(b)
+ else:
+ assert type(b) is memoryview
+ content = b.tobytes()
if sys.byteorder == 'little':
- assert str(b).startswith('\x64\x00\x00\x00\x65\x00\x00\x00')
- b[4] = '\x45'
+ assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
+ b[4] = b'\x45'[0]
else:
- assert str(b).startswith('\x00\x00\x00\x64\x00\x00\x00\x65')
- b[7] = '\x45'
- assert len(str(b)) == 4 * 10
+ assert content.startswith('\x00\x00\x00\x64\x00\x00\x00\x65')
+ b[7] = b'\x45'[0]
+ assert len(content) == 4 * 10
assert a[1] == 0x45
def test_ffi_buffer_ptr_size(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("short *", 0x4243)
b = ffi.buffer(a, 1)
- assert type(b) is buffer
- assert len(str(b)) == 1
+ if sys.version < '3':
+ assert type(b) is buffer
+ content = str(b)
+ else:
+ assert type(b) is memoryview
+ content = b.tobytes()
+ assert len(content) == 1
if sys.byteorder == 'little':
- assert str(b) == '\x43'
- b[0] = '\x62'
+ assert content == b'\x43'
+ b[0] = b'\x62'[0]
assert a[0] == 0x4262
else:
- assert str(b) == '\x42'
- b[0] = '\x63'
+ assert content == b'\x42'
+ b[0] = b'\x63'[0]
assert a[0] == 0x6343
def test_ffi_buffer_array_size(self):
ffi = FFI(backend=self.Backend())
- a1 = ffi.new("int[]", range(100, 110))
- a2 = ffi.new("int[]", range(100, 115))
- assert str(ffi.buffer(a1)) == str(ffi.buffer(a2, 4*10))
+ a1 = ffi.new("int[]", list(range(100, 110)))
+ a2 = ffi.new("int[]", list(range(100, 115)))
+ if sys.version < '3':
+ assert str(ffi.buffer(a1)) == str(ffi.buffer(a2, 4*10))
+ else:
+ assert ffi.buffer(a1).tobytes() == ffi.buffer(a2, 4*10).tobytes()
def test_ffi_buffer_with_file(self):
ffi = FFI(backend=self.Backend())
import tempfile, os, array
fd, filename = tempfile.mkstemp()
f = os.fdopen(fd, 'r+b')
- a = ffi.new("int[]", range(1005))
+ a = ffi.new("int[]", list(range(1005)))
f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
f.seek(0)
assert f.read() == array.array('i', range(1000)).tostring()
@@ -1142,13 +1169,13 @@
# which is automatically replaced with the ptr-to-function type.
ffi = FFI(backend=self.Backend())
def cb(a, b):
- return chr(ord(a) + ord(b))
+ return chr(ord(a) + ord(b)).encode()
f = ffi.callback("char cb(char, char)", cb)
- assert f('A', chr(1)) == 'B'
+ assert f(b'A', b'\x01') == b'B'
def g(callback):
- return callback('A', chr(1))
+ return callback(b'A', b'\x01')
g = ffi.callback("char g(char cb(char, char))", g)
- assert g(f) == 'B'
+ assert g(f) == b'B'
def test_vararg_callback(self):
py.test.skip("callback with '...'")
diff --git a/testing/test_function.py b/testing/test_function.py
--- a/testing/test_function.py
+++ b/testing/test_function.py
@@ -1,8 +1,13 @@
import py
from cffi import FFI
-import math, os, sys, StringIO
+import math, os, sys
from cffi.backend_ctypes import CTypesBackend
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
class FdWriteCapture(object):
"""xxx limited to capture at most 512 bytes of output, according
@@ -85,11 +90,11 @@
ffi.C = ffi.dlopen(None)
ffi.C.puts # fetch before capturing, for easier debugging
with FdWriteCapture() as fd:
- ffi.C.puts("hello")
- ffi.C.puts(" world")
+ ffi.C.puts(b"hello")
+ ffi.C.puts(b" world")
ffi.C.fflush(ffi.NULL)
res = fd.getvalue()
- assert res == 'hello\n world\n'
+ assert res == b'hello\n world\n'
def test_puts_without_const(self):
ffi = FFI(backend=self.Backend())
@@ -100,11 +105,11 @@
ffi.C = ffi.dlopen(None)
ffi.C.puts # fetch before capturing, for easier debugging
with FdWriteCapture() as fd:
- ffi.C.puts("hello")
- ffi.C.puts(" world")
+ ffi.C.puts(b"hello")
+ ffi.C.puts(b" world")
ffi.C.fflush(ffi.NULL)
res = fd.getvalue()
- assert res == 'hello\n world\n'
+ assert res == b'hello\n world\n'
def test_fputs(self):
if sys.platform == 'win32':
@@ -116,9 +121,9 @@
""")
ffi.C = ffi.dlopen(None)
with FdWriteCapture(2) as fd:
- ffi.C.fputs("hello from stderr\n", ffi.C.stderr)
+ ffi.C.fputs(b"hello from stderr\n", ffi.C.stderr)
res = fd.getvalue()
- assert res == 'hello from stderr\n'
+ assert res == b'hello from stderr\n'
def test_vararg(self):
ffi = FFI(backend=self.Backend())
@@ -128,26 +133,26 @@
""")
ffi.C = ffi.dlopen(None)
with FdWriteCapture() as fd:
- ffi.C.printf("hello with no arguments\n")
- ffi.C.printf("hello, %s!\n", ffi.new("char[]", "world"))
- ffi.C.printf(ffi.new("char[]", "hello, %s!\n"),
- ffi.new("char[]", "world2"))
- ffi.C.printf("hello int %d long %ld long long %lld\n",
+ ffi.C.printf(b"hello with no arguments\n")
+ ffi.C.printf(b"hello, %s!\n", ffi.new("char[]", b"world"))
+ ffi.C.printf(ffi.new("char[]", b"hello, %s!\n"),
+ ffi.new("char[]", b"world2"))
+ ffi.C.printf(b"hello int %d long %ld long long %lld\n",
ffi.cast("int", 42),
ffi.cast("long", 84),
ffi.cast("long long", 168))
- ffi.C.printf("hello %p\n", ffi.NULL)
+ ffi.C.printf(b"hello %p\n", ffi.NULL)
ffi.C.fflush(ffi.NULL)
res = fd.getvalue()
if sys.platform == 'win32':
- NIL = "00000000"
+ NIL = b"00000000"
else:
- NIL = "(nil)"
- assert res == ("hello with no arguments\n"
- "hello, world!\n"
- "hello, world2!\n"
- "hello int 42 long 84 long long 168\n"
- "hello " + NIL + "\n")
+ NIL = b"(nil)"
+ assert res == (b"hello with no arguments\n"
+ b"hello, world!\n"
+ b"hello, world2!\n"
+ b"hello int 42 long 84 long long 168\n"
+ b"hello " + NIL + b"\n")
def test_must_specify_type_of_vararg(self):
ffi = FFI(backend=self.Backend())
@@ -155,7 +160,7 @@
int printf(const char *format, ...);
""")
ffi.C = ffi.dlopen(None)
- e = py.test.raises(TypeError, ffi.C.printf, "hello %d\n", 42)
+ e = py.test.raises(TypeError, ffi.C.printf, b"hello %d\n", 42)
assert str(e.value) == ("argument 2 passed in the variadic part "
"needs to be a cdata object (got int)")
@@ -178,7 +183,7 @@
fptr = ffi.callback("int(*)(const char *txt)", cb)
assert fptr != ffi.callback("int(*)(const char *)", cb)
assert repr(fptr) == "<cdata 'int(*)(char *)' calling %r>" % (cb,)
- res = fptr("Hello")
+ res = fptr(b"Hello")
assert res == 42
#
ffi.cdef("""
@@ -190,10 +195,10 @@
assert fptr == ffi.C.puts
assert repr(fptr).startswith("<cdata 'int(*)(char *)' 0x")
with FdWriteCapture() as fd:
- fptr("world")
+ fptr(b"world")
ffi.C.fflush(ffi.NULL)
res = fd.getvalue()
- assert res == 'world\n'
+ assert res == b'world\n'
def test_callback_returning_void(self):
ffi = FFI(backend=self.Backend())
@@ -203,7 +208,7 @@
fptr = ffi.callback("void(*)(void)", cb)
old_stderr = sys.stderr
try:
- sys.stderr = StringIO.StringIO()
+ sys.stderr = StringIO()
returned = fptr()
printed = sys.stderr.getvalue()
finally:
@@ -220,7 +225,7 @@
int strlen(char[]);
""")
ffi.C = ffi.dlopen(None)
- p = ffi.new("char[]", "hello")
+ p = ffi.new("char[]", b"hello")
res = ffi.C.strlen(p)
assert res == 5
@@ -240,11 +245,11 @@
with FdWriteCapture(2) as fd: # capturing stderr
ffi.C.stdout = perr
try:
- ffi.C.puts("hello!") # goes to stdout, which is equal to stderr now
+ ffi.C.puts(b"hello!") # goes to stdout, which is equal to stderr now
finally:
ffi.C.stdout = pout
res = fd.getvalue()
- assert res == "hello!\n"
+ assert res == b"hello!\n"
def test_strchr(self):
ffi = FFI(backend=self.Backend())
@@ -252,9 +257,9 @@
char *strchr(const char *s, int c);
""")
ffi.C = ffi.dlopen(None)
- p = ffi.new("char[]", "hello world!")
+ p = ffi.new("char[]", b"hello world!")
q = ffi.C.strchr(p, ord('w'))
- assert str(q) == "world!"
+ assert q.value == b"world!"
def test_function_with_struct_argument(self):
if sys.platform == 'win32':
@@ -267,4 +272,4 @@
ffi.C = ffi.dlopen(None)
ina = ffi.new("struct in_addr *", [0x04040404])
a = ffi.C.inet_ntoa(ina[0])
- assert str(a) == '4.4.4.4'
+ assert a.value == b'4.4.4.4'
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -46,19 +46,19 @@
ffi = FFI()
ffi.cdef("size_t strlen(const char *s);")
lib = ffi.verify("#include <string.h>")
- assert lib.strlen("hi there!") == 9
+ assert lib.strlen(b"hi there!") == 9
def test_strlen_approximate():
ffi = FFI()
ffi.cdef("int strlen(char *s);")
lib = ffi.verify("#include <string.h>")
- assert lib.strlen("hi there!") == 9
+ assert lib.strlen(b"hi there!") == 9
def test_strlen_array_of_char():
ffi = FFI()
ffi.cdef("int strlen(char[]);")
lib = ffi.verify("#include <string.h>")
- assert lib.strlen("hello") == 5
+ assert lib.strlen(b"hello") == 5
all_integer_types = ['short', 'int', 'long', 'long long',
@@ -86,7 +86,8 @@
ffi.cdef("%s foo(%s);" % (typename, typename))
lib = ffi.verify("%s foo(%s x) { return x+1; }" % (typename, typename))
assert lib.foo(42) == 43
- assert lib.foo(44L) == 45
+ if sys.version < '3':
+ assert lib.foo(long(44)) == 45
assert lib.foo(ffi.cast(typename, 46)) == 47
py.test.raises(TypeError, lib.foo, ffi.NULL)
#
@@ -105,7 +106,8 @@
ffi = FFI()
ffi.cdef("char foo(char);")
lib = ffi.verify("char foo(char x) { return x+1; }")
- assert lib.foo("A") == "B"
+ assert lib.foo(b"A") == b"B"
+ py.test.raises(TypeError, lib.foo, b"bar")
py.test.raises(TypeError, lib.foo, "bar")
def test_wchar_type():
@@ -337,7 +339,7 @@
ffi.cdef("static char *const PP;")
lib = ffi.verify('static char *const PP = "testing!";\n')
assert ffi.typeof(lib.PP) == ffi.typeof("char *")
- assert str(lib.PP) == "testing!"
+ assert lib.PP.value == b"testing!"
def test_nonfull_enum():
ffi = FFI()
@@ -565,7 +567,7 @@
return s.a - s.b;
}
""")
- s = ffi.new("struct foo_s *", ['B', 1])
+ s = ffi.new("struct foo_s *", [b'B', 1])
assert lib.foo(50, s[0]) == ord('A')
def test_autofilled_struct_as_argument():
@@ -633,7 +635,7 @@
""")
foochar = ffi.cast("char *(*)(void)", lib.fooptr)
s = foochar()
- assert str(s) == "foobar"
+ assert s.value == b"foobar"
def test_funcptr_as_argument():
ffi = FFI()
diff --git a/testing/test_version.py b/testing/test_version.py
--- a/testing/test_version.py
+++ b/testing/test_version.py
@@ -10,12 +10,12 @@
def test_doc_version():
parent = os.path.dirname(os.path.dirname(__file__))
p = os.path.join(parent, 'doc', 'source', 'conf.py')
- content = file(p).read()
+ content = open(p).read()
#
v = cffi.__version__
assert ("version = '%s'\n" % v) in content
assert ("release = '%s'\n" % v) in content
#
p = os.path.join(parent, 'doc', 'source', 'index.rst')
- content = file(p).read()
+ content = open(p).read()
assert ("release-%s.tar.bz2" % v) in content
diff --git a/testing/test_zdistutils.py b/testing/test_zdistutils.py
--- a/testing/test_zdistutils.py
+++ b/testing/test_zdistutils.py
@@ -1,9 +1,14 @@
-import os, imp, math, StringIO, random
+import os, imp, math, random
import py
from cffi import FFI, FFIError
from cffi.verifier import Verifier
from testing.udir import udir
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
def test_write_source():
ffi = FFI()
@@ -11,7 +16,7 @@
csrc = '/*hi there!*/\n#include <math.h>\n'
v = Verifier(ffi, csrc)
v.write_source()
- with file(v.sourcefilename, 'r') as f:
+ with open(v.sourcefilename, 'r') as f:
data = f.read()
assert csrc in data
@@ -23,7 +28,7 @@
v.sourcefilename = filename = str(udir.join('write_source.c'))
v.write_source()
assert filename == v.sourcefilename
- with file(filename, 'r') as f:
+ with open(filename, 'r') as f:
data = f.read()
assert csrc in data
@@ -32,7 +37,7 @@
ffi.cdef("double sin(double x);")
csrc = '/*hi there!*/\n#include <math.h>\n'
v = Verifier(ffi, csrc)
- f = StringIO.StringIO()
+ f = StringIO()
v.write_source(file=f)
assert csrc in f.getvalue()
@@ -100,7 +105,7 @@
lib = ffi.verify(csrc)
assert lib.sin(12.3) == math.sin(12.3)
assert isinstance(ffi.verifier, Verifier)
- with file(ffi.verifier.sourcefilename, 'r') as f:
+ with open(ffi.verifier.sourcefilename, 'r') as f:
data = f.read()
assert csrc in data
More information about the pypy-commit
mailing list