Author: Armin Rigo <[email protected]>
Branch:
Changeset: r1188:7a86941ef198
Date: 2013-03-08 00:54 +0100
http://bitbucket.org/cffi/cffi/changeset/7a86941ef198/
Log: Give some compatibility explanation when passing a Python file
object to a FILE argument.
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -90,6 +90,7 @@
#define CT_CUSTOM_FIELD_POS 32768
#define CT_IS_LONGDOUBLE 65536
#define CT_IS_BOOL 131072
+#define _CT_IS_FILE 262144
#define CT_PRIMITIVE_ANY (CT_PRIMITIVE_SIGNED | \
CT_PRIMITIVE_UNSIGNED | \
CT_PRIMITIVE_CHAR | \
@@ -2041,6 +2042,18 @@
return ct_int;
}
+static int
+_explicit_error_message_for_FILE(CTypeDescrObject *ctitem)
+{
+ if (!(ctitem->ct_flags & _CT_IS_FILE))
+ return 0;
+ PyErr_SetString(PyExc_TypeError,
+ "bad argument type for 'FILE' type (note that you cannot "
+ "pass Python files directly any more since CFFI 0.6; see "
+ "demo/file1.py)");
+ return -1;
+}
+
static Py_ssize_t
_prepare_pointer_call_argument(CTypeDescrObject *ctptr, PyObject *init,
char **output_data)
@@ -2083,6 +2096,8 @@
else {
/* refuse to receive just an integer (and interpret it
as the array size) */
+ if (_explicit_error_message_for_FILE(ctitem) < 0)
+ return -1;
goto convert_default;
}
@@ -3318,9 +3333,14 @@
static PyObject *b_new_struct_type(PyObject *self, PyObject *args)
{
char *name;
+ int flag;
if (!PyArg_ParseTuple(args, "s:new_struct_type", &name))
return NULL;
- return _b_struct_or_union_type("struct", name, CT_STRUCT);
+
+ flag = CT_STRUCT;
+ if (strcmp(name, "_IO_FILE") == 0 || strcmp(name, "$FILE") == 0)
+ flag |= _CT_IS_FILE;
+ return _b_struct_or_union_type("struct", name, flag);
}
static PyObject *b_new_union_type(PyObject *self, PyObject *args)
@@ -4899,8 +4919,10 @@
static char *_cffi_to_c_pointer(PyObject *obj, CTypeDescrObject *ct)
{
char *result;
- if (convert_from_object((char *)&result, ct, obj) < 0)
+ if (convert_from_object((char *)&result, ct, obj) < 0) {
+ _explicit_error_message_for_FILE(ct->ct_itemdescr);
return NULL;
+ }
return result;
}
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2655,6 +2655,17 @@
c[1:3] = d
assert list(c) == [0, 40, 50, 30, 0]
+def test_FILE_forbidden():
+ BFILE = new_struct_type("_IO_FILE")
+ BFILEP = new_pointer_type(BFILE)
+ BFunc = new_function_type((BFILEP,), BFILEP, False)
+ func = cast(BFunc, 0)
+ with open(__file__, "rb") as f:
+ e = py.test.raises(TypeError, func, f)
+ if '__pypy__' not in sys.builtin_module_names:
+ assert ('note that you cannot pass Python files directly '
+ 'any more since CFFI 0.6') in str(e.value)
+
def test_version():
# this test is here mostly for PyPy
assert __version__ == "0.6"
diff --git a/demo/file1.py b/demo/file1.py
--- a/demo/file1.py
+++ b/demo/file1.py
@@ -3,7 +3,10 @@
#
# To access FILE objects in C that correspond directly to file descriptors
-# at the Python level, just define and use fdopen() and fclose().
+# at the Python level, just define and use fdopen() and fclose(). In
+# CFFI <= 0.5 you could directly pass Python file objects, but this is
+# not supported any more: you have to build (and close) the C-level FILEs
+# explicitly. See also 'file2.py' in the same directory for another example.
#
ffi = cffi.FFI()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit