Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r1881:a41b31913b62
Date: 2015-04-29 22:22 +0200
http://bitbucket.org/cffi/cffi/changeset/a41b31913b62/
Log: Python 3 compat
diff --git a/_cffi1/__init__.py b/_cffi1/__init__.py
--- a/_cffi1/__init__.py
+++ b/_cffi1/__init__.py
@@ -1,1 +1,1 @@
-from recompiler import make_c_source, recompile
+from .recompiler import make_c_source, recompile
diff --git a/_cffi1/_cffi_include.h b/_cffi1/_cffi_include.h
--- a/_cffi1/_cffi_include.h
+++ b/_cffi1/_cffi_include.h
@@ -148,7 +148,8 @@
#define _cffi_convert_array_from_object \
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
#define _cffi_init_module \
- ((int(*)(char *, const struct _cffi_type_context_s *))_cffi_exports[25])
+ ((PyObject *(*)(char *, const struct _cffi_type_context_s *)) \
+ _cffi_exports[25])
#define _CFFI_NUM_EXPORTS 26
typedef struct _ctypedescr CTypeDescrObject;
diff --git a/_cffi1/cffi1_module.c b/_cffi1/cffi1_module.c
--- a/_cffi1/cffi1_module.c
+++ b/_cffi1/cffi1_module.c
@@ -98,25 +98,46 @@
return -1;
}
-static int _cffi_init_module(char *module_name,
- const struct _cffi_type_context_s *ctx)
+static PyObject *_cffi_init_module(char *module_name,
+ const struct _cffi_type_context_s *ctx)
{
- PyObject *m = Py_InitModule(module_name, NULL);
+ PyObject *m;
+
+#if PY_MAJOR_VERSION >= 3
+ /* note: the module_def leaks, but anyway the C extension module cannot
+ be unloaded */
+ struct PyModuleDef *module_def;
+ module_def = PyObject_Malloc(sizeof(struct PyModuleDef));
+ if (module_def == NULL)
+ return PyErr_NoMemory();
+
+ struct PyModuleDef local_module_def = {
+ PyModuleDef_HEAD_INIT,
+ module_name,
+ NULL,
+ -1,
+ NULL, NULL, NULL, NULL, NULL
+ };
+ *module_def = local_module_def;
+ m = PyModule_Create(module_def);
+#else
+ m = Py_InitModule(module_name, NULL);
+#endif
if (m == NULL)
- return -1;
+ return NULL;
FFIObject *ffi = ffi_internal_new(&FFI_Type, ctx);
Py_XINCREF(ffi); /* make the ffi object really immortal */
if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0)
- return -1;
+ return NULL;
LibObject *lib = lib_internal_new(ffi->types_builder, module_name);
if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0)
- return -1;
+ return NULL;
if (make_included_tuples(ctx->includes, &ffi->types_builder->included_ffis,
&lib->l_includes) < 0)
- return -1;
+ return NULL;
- return 0;
+ return m;
}
diff --git a/_cffi1/cffi_opcode.py b/_cffi1/cffi_opcode.py
--- a/_cffi1/cffi_opcode.py
+++ b/_cffi1/cffi_opcode.py
@@ -139,6 +139,6 @@
F_EXTERNAL = 0x08
CLASS_NAME = {}
-for _name, _value in globals().items():
+for _name, _value in list(globals().items()):
if _name.startswith('OP_') and isinstance(_value, int):
CLASS_NAME[_value] = _name[3:]
diff --git a/_cffi1/cgc.c b/_cffi1/cgc.c
--- a/_cffi1/cgc.c
+++ b/_cffi1/cgc.c
@@ -39,7 +39,7 @@
PyObject *data;
if (const_name_pop == NULL) {
- const_name_pop = PyString_InternFromString("pop");
+ const_name_pop = PyText_InternFromString("pop");
if (const_name_pop == NULL)
return NULL;
}
diff --git a/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c
--- a/_cffi1/ffi_obj.c
+++ b/_cffi1/ffi_obj.c
@@ -424,11 +424,11 @@
char *p;
base_name_len = strlen(ct->ct_name);
- result = PyString_FromStringAndSize(NULL, base_name_len + extra_text_len);
+ result = PyBytes_FromStringAndSize(NULL, base_name_len + extra_text_len);
if (result == NULL)
return NULL;
- p = PyString_AS_STRING(result);
+ p = PyBytes_AS_STRING(result);
memcpy(p, ct->ct_name, ct->ct_name_position);
p += ct->ct_name_position;
p += extra_text_len;
@@ -473,7 +473,7 @@
if (res == NULL)
return NULL;
- p = PyString_AS_STRING(res) + ct->ct_name_position;
+ p = PyBytes_AS_STRING(res) + ct->ct_name_position;
if (add_paren)
*p++ = '(';
if (add_space)
@@ -481,6 +481,16 @@
memcpy(p, replace_with, replace_with_len);
if (add_paren)
p[replace_with_len] = ')';
+
+#if PY_MAJOR_VERSION >= 3
+ /* bytes -> unicode string */
+ PyObject *u = PyUnicode_DecodeLatin1(PyBytes_AS_STRING(res),
+ PyBytes_GET_SIZE(res),
+ NULL);
+ Py_DECREF(res);
+ res = u;
+#endif
+
return res;
}
diff --git a/_cffi1/lib_obj.c b/_cffi1/lib_obj.c
--- a/_cffi1/lib_obj.c
+++ b/_cffi1/lib_obj.c
@@ -311,7 +311,7 @@
int i;
for (i = 0; i < total; i++) {
- PyObject *s = PyString_FromString(g[i].name);
+ PyObject *s = PyText_FromString(g[i].name);
if (s == NULL) {
Py_DECREF(lst);
return NULL;
@@ -370,7 +370,7 @@
LibObject *lib;
PyObject *libname, *dict;
- libname = PyString_FromString(module_name);
+ libname = PyText_FromString(module_name);
dict = PyDict_New();
if (libname == NULL || dict == NULL) {
Py_XDECREF(dict);
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -474,7 +474,7 @@
j = 0;
while (p[j] != ',' && p[j] != '\0')
j++;
- tmp = PyString_FromStringAndSize(p, j);
+ tmp = PyText_FromStringAndSize(p, j);
if (tmp == NULL)
break;
PyTuple_SET_ITEM(enumerators, i, tmp);
diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py
--- a/_cffi1/recompiler.py
+++ b/_cffi1/recompiler.py
@@ -1,6 +1,6 @@
import os, sys
from cffi import ffiplatform, model
-from cffi_opcode import *
+from .cffi_opcode import *
class Recompiler:
@@ -225,6 +225,16 @@
#
# the init function, loading _cffi_backend and calling a method there
base_module_name = self.module_name.split('.')[-1]
+ prnt('#if PY_MAJOR_VERSION >= 3')
+ prnt('PyMODINIT_FUNC')
+ prnt('PyInit_%s(void)' % (base_module_name,))
+ prnt('{')
+ prnt(' if (_cffi_init() < 0)')
+ prnt(' return NULL;')
+ prnt(' return _cffi_init_module("%s", &_cffi_type_context);' % (
+ self.module_name,))
+ prnt('}')
+ prnt('#else')
prnt('PyMODINIT_FUNC')
prnt('init%s(void)' % (base_module_name,))
prnt('{')
@@ -233,6 +243,7 @@
prnt(' _cffi_init_module("%s", &_cffi_type_context);' % (
self.module_name,))
prnt('}')
+ prnt('#endif')
self.ffi._recompiler_module_name = self.module_name
# ----------
diff --git a/_cffi1/support.py b/_cffi1/support.py
--- a/_cffi1/support.py
+++ b/_cffi1/support.py
@@ -1,6 +1,19 @@
+import sys
-class U(object):
- def __add__(self, other):
- return eval('u'+repr(other).replace(r'\\u', r'\u')
- .replace(r'\\U', r'\U'))
-u = U()
+if sys.version_info < (3,):
+ __all__ = ['u']
+
+ class U(object):
+ def __add__(self, other):
+ return eval('u'+repr(other).replace(r'\\u', r'\u')
+ .replace(r'\\U', r'\U'))
+ u = U()
+ assert u+'a\x00b' == eval(r"u'a\x00b'")
+ assert u+'a\u1234b' == eval(r"u'a\u1234b'")
+ assert u+'a\U00012345b' == eval(r"u'a\U00012345b'")
+
+else:
+ __all__ = ['u', 'unicode', 'long']
+ u = ""
+ unicode = str
+ long = int
diff --git a/_cffi1/test_ffi_obj.py b/_cffi1/test_ffi_obj.py
--- a/_cffi1/test_ffi_obj.py
+++ b/_cffi1/test_ffi_obj.py
@@ -57,8 +57,8 @@
def test_ffi_string():
ffi = _cffi1_backend.FFI()
- p = ffi.new("char[]", "foobar\x00baz")
- assert ffi.string(p) == "foobar"
+ p = ffi.new("char[]", b"foobar\x00baz")
+ assert ffi.string(p) == b"foobar"
def test_ffi_errno():
# xxx not really checking errno, just checking that we can read/write it
diff --git a/_cffi1/test_new_ffi_1.py b/_cffi1/test_new_ffi_1.py
--- a/_cffi1/test_new_ffi_1.py
+++ b/_cffi1/test_new_ffi_1.py
@@ -1513,8 +1513,8 @@
outputfilename)
ffi2 = module.ffi
#
- p = ffi2.new("struct nonpacked *", ['A', -43141])
- assert p.a == 'A'
+ p = ffi2.new("struct nonpacked *", [b'A', -43141])
+ assert p.a == b'A'
assert p.b == -43141
#
p = ffi.new("union simple_u *", [-52525])
diff --git a/_cffi1/test_parse_c_type.py b/_cffi1/test_parse_c_type.py
--- a/_cffi1/test_parse_c_type.py
+++ b/_cffi1/test_parse_c_type.py
@@ -32,7 +32,7 @@
assert global_names == sorted(global_names)
ctx = ffi.new("struct _cffi_type_context_s *")
-c_struct_names = [ffi.new("char[]", _n) for _n in struct_names]
+c_struct_names = [ffi.new("char[]", _n.encode('ascii')) for _n in struct_names]
ctx_structs = ffi.new("struct _cffi_struct_union_s[]", len(struct_names))
for _i in range(len(struct_names)):
ctx_structs[_i].name = c_struct_names[_i]
@@ -40,14 +40,15 @@
ctx.struct_unions = ctx_structs
ctx.num_struct_unions = len(struct_names)
-c_enum_names = [ffi.new("char[]", _n) for _n in enum_names]
+c_enum_names = [ffi.new("char[]", _n.encode('ascii')) for _n in enum_names]
ctx_enums = ffi.new("struct _cffi_enum_s[]", len(enum_names))
for _i in range(len(enum_names)):
ctx_enums[_i].name = c_enum_names[_i]
ctx.enums = ctx_enums
ctx.num_enums = len(enum_names)
-c_identifier_names = [ffi.new("char[]", _n) for _n in identifier_names]
+c_identifier_names = [ffi.new("char[]", _n.encode('ascii'))
+ for _n in identifier_names]
ctx_identifiers = ffi.new("struct _cffi_typename_s[]", len(identifier_names))
for _i in range(len(identifier_names)):
ctx_identifiers[_i].name = c_identifier_names[_i]
@@ -69,7 +70,7 @@
return 1
ctx_globals = ffi.new("struct _cffi_global_s[]", len(global_names))
-c_glob_names = [ffi.new("char[]", _n) for _n in global_names]
+c_glob_names = [ffi.new("char[]", _n.encode('ascii')) for _n in global_names]
for _i, _fn in enumerate([fetch_constant_five,
fetch_constant_neg,
fetch_constant_zero]):
@@ -90,9 +91,9 @@
info.output_size = len(out)
for j in range(len(out)):
out[j] = ffi.cast("void *", -424242)
- res = lib.parse_c_type(info, input)
+ res = lib.parse_c_type(info, input.encode('ascii'))
if res < 0:
- raise ParseError(ffi.string(info.error_message),
+ raise ParseError(ffi.string(info.error_message).decode('ascii'),
info.error_location)
assert 0 <= res < len(out)
result = []
diff --git a/_cffi1/test_realize_c_type.py b/_cffi1/test_realize_c_type.py
--- a/_cffi1/test_realize_c_type.py
+++ b/_cffi1/test_realize_c_type.py
@@ -43,6 +43,6 @@
check("int(*)(long[5])", "int(*)(long *)")
def test_all_primitives():
- import cffi_opcode
+ from . import cffi_opcode
for name in cffi_opcode.PRIMITIVE_TO_INDEX:
check(name, name)
diff --git a/_cffi1/test_recompiler.py b/_cffi1/test_recompiler.py
--- a/_cffi1/test_recompiler.py
+++ b/_cffi1/test_recompiler.py
@@ -310,7 +310,7 @@
ffi = FFI()
ffi.cdef("""enum e1 { B1, A1, ... }; enum e2 { B2, A2, ... };""")
lib = verify(ffi, 'test_verify_enum',
- "enum e1 { A1, B1, C1=%d };" % sys.maxint +
+ "enum e1 { A1, B1, C1=%d };" % sys.maxsize +
"enum e2 { A2, B2, C2 };")
ffi.typeof("enum e1")
ffi.typeof("enum e2")
@@ -407,10 +407,10 @@
assert repr(ffi.cast("e1", 2)) == "<cdata 'e1' 2: AA>"
#
ffi = FFI()
- ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxint)
+ ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxsize)
lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef2',
- "typedef enum { AA=%d } e1;" % sys.maxint)
- assert lib.AA == sys.maxint
+ "typedef enum { AA=%d } e1;" % sys.maxsize)
+ assert lib.AA == sys.maxsize
assert ffi.sizeof("e1") == ffi.sizeof("long")
def test_unique_types():
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -72,6 +72,7 @@
# define PyText_FromString PyUnicode_FromString
# define PyText_FromStringAndSize PyUnicode_FromStringAndSize
# define PyText_InternInPlace PyUnicode_InternInPlace
+# define PyText_InternFromString PyUnicode_InternFromString
# define PyIntOrLong_Check PyLong_Check
#else
# define STR_OR_BYTES "str"
@@ -85,6 +86,7 @@
# define PyText_FromString PyString_FromString
# define PyText_FromStringAndSize PyString_FromStringAndSize
# define PyText_InternInPlace PyString_InternInPlace
+# define PyText_InternFromString PyString_InternFromString
# define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op))
#endif
@@ -92,6 +94,7 @@
# define PyInt_FromLong PyLong_FromLong
# define PyInt_FromSsize_t PyLong_FromSsize_t
# define PyInt_AsSsize_t PyLong_AsSsize_t
+# define PyInt_AsLong PyLong_AsLong
#endif
#if PY_MAJOR_VERSION >= 3
@@ -3404,11 +3407,11 @@
const void **pkey;
int err;
- key = PyString_FromStringAndSize(NULL, keylength * sizeof(void *));
+ key = PyBytes_FromStringAndSize(NULL, keylength * sizeof(void *));
if (key == NULL)
goto error;
- pkey = (const void **)PyString_AS_STRING(key);
+ pkey = (const void **)PyBytes_AS_STRING(key);
for (i = 0; i < keylength; i++)
pkey[i] = unique_key[i];
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit