[pypy-commit] cffi cffi-1.0: Change of scope for now: the initial goal is now to avoid breaking

arigo noreply at buildbot.pypy.org
Fri Apr 24 10:12:43 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1784:6d8fa9486905
Date: 2015-04-24 09:17 +0200
http://bitbucket.org/cffi/cffi/changeset/6d8fa9486905/

Log:	Change of scope for now: the initial goal is now to avoid breaking
	ffi.dlopen() and ffi.verify(), and only add _cffi1.recompile().

diff --git a/new/PLAN b/_cffi1/PLAN
rename from new/PLAN
rename to _cffi1/PLAN
diff --git a/new/_cffi_include.h b/_cffi1/_cffi_include.h
rename from new/_cffi_include.h
rename to _cffi1/_cffi_include.h
diff --git a/new/bsdopendirtype.py b/_cffi1/bsdopendirtype.py
rename from new/bsdopendirtype.py
rename to _cffi1/bsdopendirtype.py
diff --git a/new/bsdopendirtype_build.py b/_cffi1/bsdopendirtype_build.py
rename from new/bsdopendirtype_build.py
rename to _cffi1/bsdopendirtype_build.py
diff --git a/new/cffi-1.0.rst b/_cffi1/cffi-1.0.rst
rename from new/cffi-1.0.rst
rename to _cffi1/cffi-1.0.rst
diff --git a/new/cffi1 b/_cffi1/cffi1
rename from new/cffi1
rename to _cffi1/cffi1
diff --git a/new/cffi1_module.c b/_cffi1/cffi1_module.c
rename from new/cffi1_module.c
rename to _cffi1/cffi1_module.c
diff --git a/new/cffi_opcode.py b/_cffi1/cffi_opcode.py
rename from new/cffi_opcode.py
rename to _cffi1/cffi_opcode.py
diff --git a/new/cglob.c b/_cffi1/cglob.c
rename from new/cglob.c
rename to _cffi1/cglob.c
diff --git a/new/ffi_obj.c b/_cffi1/ffi_obj.c
rename from new/ffi_obj.c
rename to _cffi1/ffi_obj.c
diff --git a/new/lib_obj.c b/_cffi1/lib_obj.c
rename from new/lib_obj.c
rename to _cffi1/lib_obj.c
diff --git a/new/manual.c b/_cffi1/manual.c
rename from new/manual.c
rename to _cffi1/manual.c
diff --git a/new/parse_c_type.c b/_cffi1/parse_c_type.c
rename from new/parse_c_type.c
rename to _cffi1/parse_c_type.c
diff --git a/new/parse_c_type.h b/_cffi1/parse_c_type.h
rename from new/parse_c_type.h
rename to _cffi1/parse_c_type.h
diff --git a/new/readdir2.py b/_cffi1/readdir2.py
rename from new/readdir2.py
rename to _cffi1/readdir2.py
diff --git a/new/readdir2_build.py b/_cffi1/readdir2_build.py
rename from new/readdir2_build.py
rename to _cffi1/readdir2_build.py
diff --git a/new/realize_c_type.c b/_cffi1/realize_c_type.c
rename from new/realize_c_type.c
rename to _cffi1/realize_c_type.c
diff --git a/new/recompiler.py b/_cffi1/recompiler.py
rename from new/recompiler.py
rename to _cffi1/recompiler.py
diff --git a/new/setup.py b/_cffi1/setup.py
rename from new/setup.py
rename to _cffi1/setup.py
diff --git a/new/setup_manual.py b/_cffi1/setup_manual.py
rename from new/setup_manual.py
rename to _cffi1/setup_manual.py
diff --git a/new/test_dlopen.py b/_cffi1/test_dlopen.py
rename from new/test_dlopen.py
rename to _cffi1/test_dlopen.py
diff --git a/new/test_ffi_obj.py b/_cffi1/test_ffi_obj.py
rename from new/test_ffi_obj.py
rename to _cffi1/test_ffi_obj.py
diff --git a/new/test_parse_c_type.py b/_cffi1/test_parse_c_type.py
rename from new/test_parse_c_type.py
rename to _cffi1/test_parse_c_type.py
diff --git a/new/test_realize_c_type.py b/_cffi1/test_realize_c_type.py
rename from new/test_realize_c_type.py
rename to _cffi1/test_realize_c_type.py
diff --git a/new/test_recompiler.py b/_cffi1/test_recompiler.py
rename from new/test_recompiler.py
rename to _cffi1/test_recompiler.py
diff --git a/new/test_verify1.py b/_cffi1/test_verify1.py
rename from new/test_verify1.py
rename to _cffi1/test_verify1.py
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -5402,6 +5402,12 @@
     return NULL;
 }
 
+static PyObject *b__get_types(PyObject *self, PyObject *noarg)
+{
+    return PyTuple_Pack(2, (PyObject *)&CData_Type,
+                           (PyObject *)&CTypeDescr_Type);
+}
+
 /************************************************************/
 
 static char _testfunc0(char a, char b)
@@ -5706,6 +5712,7 @@
 #ifdef MS_WIN32
     {"getwinerror", b_getwinerror, METH_VARARGS},
 #endif
+    {"_get_types", b__get_types, METH_NOARGS},
     {"_testfunc", b__testfunc, METH_VARARGS},
     {"_testbuff", b__testbuff, METH_VARARGS},
     {NULL,     NULL}    /* Sentinel */
@@ -5820,7 +5827,7 @@
 }
 #endif
 
-#include "../new/cffi1_module.c"
+#include "../_cffi1/cffi1_module.c"
 
 static void *cffi_exports[] = {
     (void *)26,
@@ -5861,7 +5868,7 @@
 #if PY_MAJOR_VERSION >= 3
 static struct PyModuleDef FFIBackendModuleDef = {
   PyModuleDef_HEAD_INIT,
-  "_cffi1_backend",
+  "_cffi_backend",
   NULL,
   -1,
   FFIBackendMethods,
@@ -5875,7 +5882,7 @@
 #define INITERROR return
 
 PyMODINIT_FUNC
-init_cffi1_backend(void)
+init_cffi_backend(void)
 #endif
 {
     PyObject *m, *v;
@@ -5892,7 +5899,7 @@
 #if PY_MAJOR_VERSION >= 3
     m = PyModule_Create(&FFIBackendModuleDef);
 #else
-    m = Py_InitModule("_cffi1_backend", FFIBackendMethods);
+    m = Py_InitModule("_cffi_backend", FFIBackendMethods);
 #endif
 
     if (m == NULL)
diff --git a/cffi/__init__.py b/cffi/__init__.py
--- a/cffi/__init__.py
+++ b/cffi/__init__.py
@@ -1,10 +1,13 @@
 __all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
            'FFIError']
 
-from .api import FFI, CDefError
+from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-FFIError = FFI.error    # backward compatibility
-
 __version__ = "1.0.0"
 __version_info__ = (1, 0, 0)
+
+# The verifier module file names are based on the CRC32 of a string that
+# contains the following version number.  It may be older than __version__
+# if nothing is clearly incompatible.
+__version_verifier_modules__ = "0.8.6"
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -1,9 +1,5 @@
 import sys, types
 from .lock import allocate_lock
-import _cffi1_backend
-
-class DeprecatedError(Exception):
-    pass
 
 try:
     callable
@@ -19,7 +15,8 @@
     basestring = str
 
 
-FFIError = _cffi1_backend.FFI.error
+class FFIError(Exception):
+    pass
 
 class CDefError(Exception):
     def __str__(self):
@@ -30,7 +27,7 @@
         return '%s%s' % (line, self.args[0])
 
 
-class FFI(_cffi1_backend.FFI):
+class FFI(object):
     r'''
     The main top-level class that you instantiate once, or once per module.
 
@@ -48,16 +45,21 @@
         C.printf("hello, %s!\n", ffi.new("char[]", "world"))
     '''
 
-    def __init__(self):
+    def __init__(self, backend=None):
         """Create an FFI instance.  The 'backend' argument is used to
         select a non-default backend, mostly for tests.
         """
         from . import cparser, model
-        from . import __version__
-
-        backend = _cffi1_backend
-        assert backend.__version__ == __version__, \
-            "version mismatch, %s != %s" % (backend.__version__, __version__)
+        if backend is None:
+            # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with
+            # _cffi_backend.so compiled.
+            import _cffi_backend as backend
+            from . import __version__
+            assert backend.__version__ == __version__, \
+               "version mismatch, %s != %s" % (backend.__version__, __version__)
+            # (If you insist you can also try to pass the option
+            # 'backend=backend_ctypes.CTypesBackend()', but don't
+            # rely on it!  It's probably not going to work well.)
 
         self._backend = backend
         self._lock = allocate_lock()
@@ -75,9 +77,18 @@
             if name.startswith('RTLD_'):
                 setattr(self, name, getattr(backend, name))
         #
-        #with self._lock:
-        #    self.BVoidP = self._get_cached_btype(model.voidp_type)
-        #    self.BCharA = self._get_cached_btype(model.char_array_type)
+        with self._lock:
+            self.BVoidP = self._get_cached_btype(model.voidp_type)
+            self.BCharA = self._get_cached_btype(model.char_array_type)
+        if isinstance(backend, types.ModuleType):
+            # _cffi_backend: attach these constants to the class
+            if not hasattr(FFI, 'NULL'):
+                FFI.NULL = self.cast(self.BVoidP, 0)
+                FFI.CData, FFI.CType = backend._get_types()
+        else:
+            # ctypes backend: attach these constants to the instance
+            self.NULL = self.cast(self.BVoidP, 0)
+            self.CData, self.CType = backend._get_types()
 
     def cdef(self, csource, override=False, packed=False):
         """Parse the given C source.  This registers all declared functions,
@@ -97,7 +108,6 @@
             if override:
                 for cache in self._function_caches:
                     cache.clear()
-        _set_cdef_types(self)
 
     def dlopen(self, name, flags=0):
         """Load and return a dynamic library identified by 'name'.
@@ -145,7 +155,7 @@
                             "pointer-to-function type" % (cdecl,))
         return btype
 
-    def XXXtypeof(self, cdecl):
+    def typeof(self, cdecl):
         """Parse the C type given as a string and return the
         corresponding <ctype> object.
         It can also be used on 'cdata' instance to get its C type.
@@ -164,7 +174,7 @@
                 return self._get_cached_btype(cdecl._cffi_base_type)
         raise TypeError(type(cdecl))
 
-    def XXXsizeof(self, cdecl):
+    def sizeof(self, cdecl):
         """Return the size in bytes of the argument.  It can be a
         string naming a C type, or a 'cdata' instance.
         """
@@ -174,7 +184,7 @@
         else:
             return self._backend.sizeof(cdecl)
 
-    def XXXalignof(self, cdecl):
+    def alignof(self, cdecl):
         """Return the natural alignment size in bytes of the C type
         given as a string.
         """
@@ -182,7 +192,7 @@
             cdecl = self._typeof(cdecl)
         return self._backend.alignof(cdecl)
 
-    def XXXoffsetof(self, cdecl, *fields_or_indexes):
+    def offsetof(self, cdecl, *fields_or_indexes):
         """Return the offset of the named field inside the given
         structure or array, which must be given as a C type name.  
         You can give several field names in case of nested structures.
@@ -193,7 +203,7 @@
             cdecl = self._typeof(cdecl)
         return self._typeoffsetof(cdecl, *fields_or_indexes)[1]
 
-    def XXXnew(self, cdecl, init=None):
+    def new(self, cdecl, init=None):
         """Allocate an instance according to the specified C type and
         return a pointer to it.  The specified C type must be either a
         pointer or an array: ``new('X *')`` allocates an X and returns
@@ -220,7 +230,7 @@
             cdecl = self._typeof(cdecl)
         return self._backend.newp(cdecl, init)
 
-    def XXXcast(self, cdecl, source):
+    def cast(self, cdecl, source):
         """Similar to a C cast: returns an instance of the named C
         type initialized with the given 'source'.  The source is
         casted between integers or pointers of any type.
@@ -229,7 +239,7 @@
             cdecl = self._typeof(cdecl)
         return self._backend.cast(cdecl, source)
 
-    def XXXstring(self, cdata, maxlen=-1):
+    def string(self, cdata, maxlen=-1):
         """Return a Python string (or unicode string) from the 'cdata'.
         If 'cdata' is a pointer or array of characters or bytes, returns
         the null-terminated string.  The returned string extends until
@@ -247,7 +257,7 @@
         """
         return self._backend.string(cdata, maxlen)
 
-    def XXXbuffer(self, cdata, size=-1):
+    def buffer(self, cdata, size=-1):
         """Return a read-write buffer object that references the raw C data
         pointed to by the given 'cdata'.  The 'cdata' must be a pointer or
         an array.  Can be passed to functions expecting a buffer, or directly
@@ -260,7 +270,7 @@
         """
         return self._backend.buffer(cdata, size)
 
-    def XXXfrom_buffer(self, python_buffer):
+    def from_buffer(self, python_buffer):
         """Return a <cdata 'char[]'> that points to the data of the
         given Python object, which must support the buffer interface.
         Note that this is not meant to be used on the built-in types str,
@@ -270,7 +280,7 @@
         """
         return self._backend.from_buffer(self.BCharA, python_buffer)
 
-    def XXXcallback(self, cdecl, python_callable=None, error=None):
+    def callback(self, cdecl, python_callable=None, error=None):
         """Return a callback object or a decorator making such a
         callback object.  'cdecl' must name a C function pointer type.
         The callback invokes the specified 'python_callable' (which may
@@ -290,7 +300,7 @@
         else:
             return callback_decorator_wrap(python_callable)  # direct mode
 
-    def XXXgetctype(self, cdecl, replace_with=''):
+    def getctype(self, cdecl, replace_with=''):
         """Return a string giving the C type 'cdecl', which may be itself
         a string or a <ctype> object.  If 'replace_with' is given, it gives
         extra text to append (or insert for more complicated C types), like
@@ -306,7 +316,7 @@
             replace_with = ' ' + replace_with
         return self._backend.getcname(cdecl, replace_with)
 
-    def XXXgc(self, cdata, destructor):
+    def gc(self, cdata, destructor):
         """Return a new cdata object that points to the same
         data.  Later, when this new cdata object is garbage-collected,
         'destructor(old_cdata_object)' will be called.
@@ -320,15 +330,18 @@
             return gc_weakrefs.build(cdata, destructor)
 
     def _get_cached_btype(self, type):
-        raise DeprecatedError
+        assert self._lock.acquire(False) is False
+        # call me with the lock!
+        try:
+            BType = self._cached_btypes[type]
+        except KeyError:
+            finishlist = []
+            BType = type.get_cached_btype(self, finishlist)
+            for type in finishlist:
+                type.finish_backend_type(self, finishlist)
+        return BType
 
-    def verify(self, source='', **kwargs):
-        from recompiler import verify    # XXX must be in the current dir
-        FFI._verify_counter += 1
-        return verify(self, 'verify%d' % FFI._verify_counter, source, **kwargs)
-    _verify_counter = 0
-
-    def XXXverify(self, source='', tmpdir=None, **kwargs):
+    def verify(self, source='', tmpdir=None, **kwargs):
         """Verify that the current ffi signatures compile on this
         machine, and return a dynamic library object.  The dynamic
         library can be used to call functions and access global
@@ -362,10 +375,10 @@
         return self._backend.get_errno()
     def _set_errno(self, errno):
         self._backend.set_errno(errno)
-    XXXerrno = property(_get_errno, _set_errno, None,
+    errno = property(_get_errno, _set_errno, None,
                      "the value of 'errno' from/to the C calls")
 
-    def XXXgetwinerror(self, code=-1):
+    def getwinerror(self, code=-1):
         return self._backend.getwinerror(code)
 
     def _pointer_to(self, ctype):
@@ -373,7 +386,7 @@
         with self._lock:
             return model.pointer_cache(self, ctype)
 
-    def XXXaddressof(self, cdata, *fields_or_indexes):
+    def addressof(self, cdata, *fields_or_indexes):
         """Return the address of a <cdata 'struct-or-union'>.
         If 'fields_or_indexes' are given, returns the address of that
         field or array item in the structure or array, recursively in
@@ -405,7 +418,6 @@
         variables, which must anyway be accessed directly from the
         lib object returned by the original FFI instance.
         """
-        XXX
         with ffi_to_include._lock:
             with self._lock:
                 self._parser.include(ffi_to_include._parser)
@@ -413,10 +425,10 @@
                 self._cdefsources.extend(ffi_to_include._cdefsources)
                 self._cdefsources.append(']')
 
-    def XXXnew_handle(self, x):
+    def new_handle(self, x):
         return self._backend.newp_handle(self.BVoidP, x)
 
-    def XXXfrom_handle(self, x):
+    def from_handle(self, x):
         return self._backend.from_handle(x)
 
     def set_unicode(self, enabled_flag):
@@ -426,7 +438,6 @@
         declare these types to be (pointers to) plain 8-bit characters.
         This is mostly for backward compatibility; you usually want True.
         """
-        XXX
         if self._windows_unicode is not None:
             raise ValueError("set_unicode() can only be called once")
         enabled_flag = bool(enabled_flag)
@@ -566,56 +577,3 @@
     else:
         with ffi._lock:
             return ffi._get_cached_btype(tp)
-
-def _set_cdef_types(ffi):
-    from . import model
-
-    all_structs = {}
-    all_typedefs = {}
-    for name, tp in ffi._parser._declarations.items():
-        kind, basename = name.split(' ', 1)
-        if kind == 'struct' or kind == 'union' or kind == 'anonymous':
-            all_structs[tp.name] = tp
-        elif kind == 'typedef':
-            all_typedefs[basename] = tp
-            if getattr(tp, "origin", None) == "unknown_type":
-                all_structs[tp.name] = tp
-            elif isinstance(tp, model.NamedPointerType):
-                all_structs[tp.totype.name] = tp.totype
-
-    struct_unions = []
-    pending_completion = []
-    for name, tp in sorted(all_structs.items()):
-        if not isinstance(tp, model.UnionType):
-            BType = _cffi1_backend.new_struct_type(name)
-        else:
-            BType = _cffi1_backend.new_union_type(name)
-        struct_unions.append(name)
-        struct_unions.append(BType)
-        if not tp.partial and tp.fldtypes is not None:
-            pending_completion.append((tp, BType))
-    #
-    typenames = []
-    for name, tp in sorted(all_typedefs.items()):
-        cname = tp._get_c_name()
-        if cname == name:
-            assert isinstance(tp, model.StructOrUnionOrEnum)
-            cname = '%s %s' % (tp.kind, tp.name)
-        try:
-            BType = ffi.typeof(cname)
-        except ffi.error:
-            ffi.__set_types(struct_unions, typenames)
-            BType = ffi.typeof(cname)
-        typenames.append(name)
-        typenames.append(BType)
-    #
-    ffi.__set_types(struct_unions, typenames)
-    #
-    for tp, BType in pending_completion:
-        fldtypes = [ffi.typeof(ftp._get_c_name()) for ftp in tp.fldtypes]
-        lst = list(zip(tp.fldnames, fldtypes, tp.fldbitsize))
-        sflags = 0
-        if tp.packed:
-            sflags = 8    # SF_PACKED
-        _cffi1_backend.complete_struct_or_union(BType, lst, ffi,
-                                                -1, -1, sflags)
diff --git a/setup_base.py b/setup_base.py
--- a/setup_base.py
+++ b/setup_base.py
@@ -9,7 +9,9 @@
     from distutils.core import setup
     from distutils.extension import Extension
     standard = '__pypy__' not in sys.modules
-    setup(ext_modules=[Extension(name = '_cffi1_backend',
+    setup(packages=['cffi'],
+          requires=['pycparser'],
+          ext_modules=[Extension(name = '_cffi_backend',
                                  include_dirs=include_dirs,
                                  sources=sources,
                                  libraries=libraries,


More information about the pypy-commit mailing list