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

Reply via email to