Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r83723:cb355ffb0a18
Date: 2016-04-17 19:16 +0200
http://bitbucket.org/pypy/pypy/changeset/cb355ffb0a18/

Log:    update the version number of cffi to 1.6.0 and import the current
        cffi head (a1edd8c65596)

diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.5.2
+Version: 1.6.0
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.5.2"
-__version_info__ = (1, 5, 2)
+__version__ = "1.6.0"
+__version_info__ = (1, 6, 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__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
         f = PySys_GetObject((char *)"stderr");
         if (f != NULL && f != Py_None) {
             PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
-                               "\ncompiled with cffi version: 1.5.2"
+                               "\ncompiled with cffi version: 1.6.0"
                                "\n_cffi_backend module: ", f);
             modules = PyImport_GetModuleDict();
             mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -299,6 +299,23 @@
         """
         return self._backend.string(cdata, maxlen)
 
+    def unpack(self, cdata, length):
+        """Unpack an array of C data of the given length, 
+        returning a Python string/unicode/list.
+
+        If 'cdata' is a pointer to 'char', returns a byte string.
+        It does not stop at the first null.  This is equivalent to:
+        ffi.buffer(cdata, length)[:]
+
+        If 'cdata' is a pointer to 'wchar_t', returns a unicode string.
+        'length' is measured in wchar_t's; it is not the size in bytes.
+
+        If 'cdata' is a pointer to anything else, returns a list of
+        'length' items.  This is a faster equivalent to:
+        [cdata[i] for i in range(length)]
+        """
+        return self._backend.unpack(cdata, length)
+
     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
@@ -721,6 +738,26 @@
         raise ValueError("ffi.def_extern() is only available on API-mode FFI "
                          "objects")
 
+    def list_types(self):
+        """Returns the user type names known to this FFI instance.
+        This returns a tuple containing three lists of names:
+        (typedef_names, names_of_structs, names_of_unions)
+        """
+        typedefs = []
+        structs = []
+        unions = []
+        for key in self._parser._declarations:
+            if key.startswith('typedef '):
+                typedefs.append(key[8:])
+            elif key.startswith('struct '):
+                structs.append(key[7:])
+            elif key.startswith('union '):
+                unions.append(key[6:])
+        typedefs.sort()
+        structs.sort()
+        unions.sort()
+        return (typedefs, structs, unions)
+
 
 def _load_backend_lib(backend, name, flags):
     if name is None:
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -1231,7 +1231,7 @@
             if c == '\n': return '\\n'
             return '\\%03o' % ord(c)
         lines = []
-        for line in s.splitlines(True):
+        for line in s.splitlines(True) or ['']:
             lines.append('"%s"' % ''.join([_char_repr(c) for c in line]))
         return ' \\\n'.join(lines)
 
@@ -1319,7 +1319,9 @@
                 s = s.encode('ascii')
             super(NativeIO, self).write(s)
 
-def _make_c_or_py_source(ffi, module_name, preamble, target_file):
+def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose):
+    if verbose:
+        print("generating %s" % (target_file,))
     recompiler = Recompiler(ffi, module_name,
                             target_is_python=(preamble is None))
     recompiler.collect_type_table()
@@ -1331,6 +1333,8 @@
         with open(target_file, 'r') as f1:
             if f1.read(len(output) + 1) != output:
                 raise IOError
+        if verbose:
+            print("(already up-to-date)")
         return False     # already up-to-date
     except IOError:
         tmp_file = '%s.~%d' % (target_file, os.getpid())
@@ -1343,12 +1347,14 @@
             os.rename(tmp_file, target_file)
         return True
 
-def make_c_source(ffi, module_name, preamble, target_c_file):
+def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False):
     assert preamble is not None
-    return _make_c_or_py_source(ffi, module_name, preamble, target_c_file)
+    return _make_c_or_py_source(ffi, module_name, preamble, target_c_file,
+                                verbose)
 
-def make_py_source(ffi, module_name, target_py_file):
-    return _make_c_or_py_source(ffi, module_name, None, target_py_file)
+def make_py_source(ffi, module_name, target_py_file, verbose=False):
+    return _make_c_or_py_source(ffi, module_name, None, target_py_file,
+                                verbose)
 
 def _modname_to_file(outputdir, modname, extension):
     parts = modname.split('.')
@@ -1438,7 +1444,8 @@
                 target = '*'
         #
         ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds)
-        updated = make_c_source(ffi, module_name, preamble, c_file)
+        updated = make_c_source(ffi, module_name, preamble, c_file,
+                                verbose=compiler_verbose)
         if call_c_compiler:
             patchlist = []
             cwd = os.getcwd()
@@ -1458,7 +1465,8 @@
     else:
         if c_file is None:
             c_file, _ = _modname_to_file(tmpdir, module_name, '.py')
-        updated = make_py_source(ffi, module_name, c_file)
+        updated = make_py_source(ffi, module_name, c_file,
+                                 verbose=compiler_verbose)
         if call_c_compiler:
             return c_file
         else:
@@ -1484,4 +1492,7 @@
     def typeof_disabled(*args, **kwds):
         raise NotImplementedError
     ffi._typeof = typeof_disabled
+    for name in dir(ffi):
+        if not name.startswith('_') and not hasattr(module.ffi, name):
+            setattr(ffi, name, NotImplemented)
     return module.lib
diff --git a/pypy/module/_cffi_backend/__init__.py 
b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -3,7 +3,7 @@
 from rpython.rlib import rdynload, clibffi, entrypoint
 from rpython.rtyper.lltypesystem import rffi
 
-VERSION = "1.5.2"
+VERSION = "1.6.0"
 
 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
 try:
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
 # ____________________________________________________________
 
 import sys
-assert __version__ == "1.5.2", ("This test_c.py file is for testing a version"
+assert __version__ == "1.6.0", ("This test_c.py file is for testing a version"
                                 " of cffi that differs from the one that we"
                                 " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py
@@ -424,3 +424,59 @@
     def test_ffi_def_extern(self):
         ffi = FFI()
         py.test.raises(ValueError, ffi.def_extern)
+
+    def test_introspect_typedef(self):
+        ffi = FFI()
+        ffi.cdef("typedef int foo_t;")
+        assert ffi.list_types() == (['foo_t'], [], [])
+        assert ffi.typeof('foo_t').kind == 'primitive'
+        assert ffi.typeof('foo_t').cname == 'int'
+        #
+        ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
+        assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'foo_t', 'g_t'],
+                                    [], [])
+
+    def test_introspect_struct(self):
+        ffi = FFI()
+        ffi.cdef("struct foo_s { int a; };")
+        assert ffi.list_types() == ([], ['foo_s'], [])
+        assert ffi.typeof('struct foo_s').kind == 'struct'
+        assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
+
+    def test_introspect_union(self):
+        ffi = FFI()
+        ffi.cdef("union foo_s { int a; };")
+        assert ffi.list_types() == ([], [], ['foo_s'])
+        assert ffi.typeof('union foo_s').kind == 'union'
+        assert ffi.typeof('union foo_s').cname == 'union foo_s'
+
+    def test_introspect_struct_and_typedef(self):
+        ffi = FFI()
+        ffi.cdef("typedef struct { int a; } foo_t;")
+        assert ffi.list_types() == (['foo_t'], [], [])
+        assert ffi.typeof('foo_t').kind == 'struct'
+        assert ffi.typeof('foo_t').cname == 'foo_t'
+
+    def test_introspect_included_type(self):
+        ffi1 = FFI()
+        ffi2 = FFI()
+        ffi1.cdef("typedef signed char schar_t; struct sint_t { int x; };")
+        ffi2.include(ffi1)
+        assert ffi1.list_types() == ffi2.list_types() == (
+            ['schar_t'], ['sint_t'], [])
+
+    def test_introspect_order(self):
+        ffi = FFI()
+        ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;")
+        ffi.cdef("union g   { int a; }; typedef struct cc  { int a; } bbb;")
+        ffi.cdef("union aa  { int a; }; typedef struct a   { int a; } bb;")
+        assert ffi.list_types() == (['b', 'bb', 'bbb'],
+                                    ['a', 'cc', 'ccc'],
+                                    ['aa', 'aaa', 'g'])
+
+    def test_unpack(self):
+        ffi = FFI()
+        p = ffi.new("char[]", b"abc\x00def")
+        assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
+        p = ffi.new("int[]", [-123456789])
+        assert ffi.unpack(p, 1) == [-123456789]
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
@@ -496,3 +496,10 @@
         assert i < 20
         time.sleep(0.51)
     assert seen == ['init!', 'oops'] * 3
+
+def test_unpack():
+    ffi = _cffi1_backend.FFI()
+    p = ffi.new("char[]", b"abc\x00def")
+    assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
+    p = ffi.new("int[]", [-123456789])
+    assert ffi.unpack(p, 1) == [-123456789]
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -1744,3 +1744,125 @@
     lib.mycb1 = lib.foo
     assert lib.mycb1(200) == 242
     assert lib.indirect_call(300) == 342
+
+def test_introspect_function():
+    ffi = FFI()
+    ffi.cdef("float f1(double);")
+    lib = verify(ffi, 'test_introspect_function', """
+        float f1(double x) { return x; }
+    """)
+    assert dir(lib) == ['f1']
+    FUNC = ffi.typeof(lib.f1)
+    assert FUNC.kind == 'function'
+    assert FUNC.args[0].cname == 'double'
+    assert FUNC.result.cname == 'float'
+    assert ffi.typeof(ffi.addressof(lib, 'f1')) is FUNC
+
+def test_introspect_global_var():
+    ffi = FFI()
+    ffi.cdef("float g1;")
+    lib = verify(ffi, 'test_introspect_global_var', """
+        float g1;
+    """)
+    assert dir(lib) == ['g1']
+    FLOATPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
+    assert FLOATPTR.kind == 'pointer'
+    assert FLOATPTR.item.cname == 'float'
+
+def test_introspect_global_var_array():
+    ffi = FFI()
+    ffi.cdef("float g1[100];")
+    lib = verify(ffi, 'test_introspect_global_var_array', """
+        float g1[100];
+    """)
+    assert dir(lib) == ['g1']
+    FLOATARRAYPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
+    assert FLOATARRAYPTR.kind == 'pointer'
+    assert FLOATARRAYPTR.item.kind == 'array'
+    assert FLOATARRAYPTR.item.length == 100
+    assert ffi.typeof(lib.g1) is FLOATARRAYPTR.item
+
+def test_introspect_integer_const():
+    ffi = FFI()
+    ffi.cdef("#define FOO 42")
+    lib = verify(ffi, 'test_introspect_integer_const', """
+        #define FOO 42
+    """)
+    assert dir(lib) == ['FOO']
+    assert lib.FOO == ffi.integer_const('FOO') == 42
+
+def test_introspect_typedef():
+    ffi = FFI()
+    ffi.cdef("typedef int foo_t;")
+    lib = verify(ffi, 'test_introspect_typedef', """
+        typedef int foo_t;
+    """)
+    assert ffi.list_types() == (['foo_t'], [], [])
+    assert ffi.typeof('foo_t').kind == 'primitive'
+    assert ffi.typeof('foo_t').cname == 'int'
+
+def test_introspect_typedef_multiple():
+    ffi = FFI()
+    ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
+    lib = verify(ffi, 'test_introspect_typedef_multiple', """
+        typedef signed char a_t, c_t, g_t, b_t;
+    """)
+    assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'g_t'], [], [])
+
+def test_introspect_struct():
+    ffi = FFI()
+    ffi.cdef("struct foo_s { int a; };")
+    lib = verify(ffi, 'test_introspect_struct', """
+        struct foo_s { int a; };
+    """)
+    assert ffi.list_types() == ([], ['foo_s'], [])
+    assert ffi.typeof('struct foo_s').kind == 'struct'
+    assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
+
+def test_introspect_union():
+    ffi = FFI()
+    ffi.cdef("union foo_s { int a; };")
+    lib = verify(ffi, 'test_introspect_union', """
+        union foo_s { int a; };
+    """)
+    assert ffi.list_types() == ([], [], ['foo_s'])
+    assert ffi.typeof('union foo_s').kind == 'union'
+    assert ffi.typeof('union foo_s').cname == 'union foo_s'
+
+def test_introspect_struct_and_typedef():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int a; } foo_t;")
+    lib = verify(ffi, 'test_introspect_struct_and_typedef', """
+        typedef struct { int a; } foo_t;
+    """)
+    assert ffi.list_types() == (['foo_t'], [], [])
+    assert ffi.typeof('foo_t').kind == 'struct'
+    assert ffi.typeof('foo_t').cname == 'foo_t'
+
+def test_introspect_included_type():
+    SOURCE = """
+        typedef signed char schar_t;
+        struct sint_t { int x; };
+    """
+    ffi1 = FFI()
+    ffi1.cdef(SOURCE)
+    ffi2 = FFI()
+    ffi2.include(ffi1)
+    verify(ffi1, "test_introspect_included_type_parent", SOURCE)
+    verify(ffi2, "test_introspect_included_type", SOURCE)
+    assert ffi1.list_types() == ffi2.list_types() == (
+            ['schar_t'], ['sint_t'], [])
+
+def test_introspect_order():
+    ffi = FFI()
+    ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;")
+    ffi.cdef("union g   { int a; }; typedef struct cc  { int a; } bbb;")
+    ffi.cdef("union aa  { int a; }; typedef struct a   { int a; } bb;")
+    verify(ffi, "test_introspect_order", """
+        union aaa { int a; }; typedef struct ccc { int a; } b;
+        union g   { int a; }; typedef struct cc  { int a; } bbb;
+        union aa  { int a; }; typedef struct a   { int a; } bb;
+    """)
+    assert ffi.list_types() == (['b', 'bb', 'bbb'],
+                                    ['a', 'cc', 'ccc'],
+                                    ['aa', 'aaa', 'g'])
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py
@@ -695,25 +695,14 @@
     assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
     assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
     #
-    # try again
-    ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
-    assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
-    #
     assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': 
-10}
     assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
 
 def test_full_enum():
     ffi = FFI()
     ffi.cdef("enum ee { EE1, EE2, EE3 };")
-    ffi.verify("enum ee { EE1, EE2, EE3 };")
-    py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };")
-    # disabled: for now, we always accept and fix transparently constant values
-    #e = py.test.raises(VerificationError, ffi.verify,
-    #                   "enum ee { EE1, EE3, EE2 };")
-    #assert str(e.value) == 'enum ee: EE2 has the real value 2, not 1'
-    # extra items cannot be seen and have no bad consequence anyway
-    lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };")
-    assert lib.EE3 == 2
+    lib = ffi.verify("enum ee { EE1, EE2, EE3 };")
+    assert [lib.EE1, lib.EE2, lib.EE3] == [0, 1, 2]
 
 def test_enum_usage():
     ffi = FFI()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py 
b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
--- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py
@@ -143,7 +143,7 @@
         env_extra[envname] = libpath
         for key, value in sorted(env_extra.items()):
             if os.environ.get(key) != value:
-                print '* setting env var %r to %r' % (key, value)
+                print('* setting env var %r to %r' % (key, value))
                 os.environ[key] = value
 
     def execute(self, name):
@@ -165,6 +165,9 @@
 
 
 class TestBasic(EmbeddingTests):
+    def test_empty(self):
+        empty_cffi = self.prepare_module('empty')
+
     def test_basic(self):
         add1_cffi = self.prepare_module('add1')
         self.compile('add1-test', [add1_cffi])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to