Commits

Philip Jenvey committed b2f3497 Merge

merge default

Comments (0)

Files changed (15)

lib_pypy/cffi/__init__.py

 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "0.6"
-__version_info__ = (0, 6)
+__version__ = "0.7"
+__version_info__ = (0, 7)

lib_pypy/cffi/api.py

             if name.startswith('RTLD_'):
                 setattr(self, name, getattr(backend, name))
         #
-        BVoidP = self._get_cached_btype(model.voidp_type)
+        self.BVoidP = self._get_cached_btype(model.voidp_type)
         if isinstance(backend, types.ModuleType):
             # _cffi_backend: attach these constants to the class
             if not hasattr(FFI, 'NULL'):
-                FFI.NULL = self.cast(BVoidP, 0)
+                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(BVoidP, 0)
+            self.NULL = self.cast(self.BVoidP, 0)
             self.CData, self.CType = backend._get_types()
 
     def cdef(self, csource, override=False):
         self._cdefsources.extend(ffi_to_include._cdefsources)
         self._cdefsources.append(']')
 
+    def new_handle(self, x):
+        return self._backend.newp_handle(self.BVoidP, x)
+
+    def from_handle(self, x):
+        return self._backend.from_handle(x)
+
 
 def _make_ffi_library(ffi, libname, flags):
     import os
             BType = ffi._get_cached_btype(tp)
             try:
                 value = backendlib.load_function(BType, name)
-            except KeyError:
-                raise AttributeError(name)
+            except KeyError as e:
+                raise AttributeError('%s: %s' % (name, e))
             library.__dict__[name] = value
             return
         #

lib_pypy/cffi/backend_ctypes.py

 class CTypesData(object):
     __metaclass__ = CTypesType
     __slots__ = ['__weakref__']
+    __name__ = '<cdata>'
 
     def __init__(self, *args):
         raise TypeError("cannot instantiate %r" % (self.__class__,))
         elif BItem in (getbtype(model.PrimitiveType('signed char')),
                        getbtype(model.PrimitiveType('unsigned char'))):
             kind = 'bytep'
+        elif BItem is getbtype(model.void_type):
+            kind = 'voidp'
         else:
             kind = 'generic'
         #
             def __setitem__(self, index, value):
                 self._as_ctype_ptr[index] = BItem._to_ctypes(value)
 
-            if kind == 'charp':
+            if kind == 'charp' or kind == 'voidp':
                 @classmethod
-                def _arg_to_ctypes(cls, value):
-                    if isinstance(value, bytes):
-                        return ctypes.c_char_p(value)
+                def _arg_to_ctypes(cls, *value):
+                    if value and isinstance(value[0], bytes):
+                        return ctypes.c_char_p(value[0])
                     else:
-                        return super(CTypesPtr, cls)._arg_to_ctypes(value)
+                        return super(CTypesPtr, cls)._arg_to_ctypes(*value)
 
             if kind == 'charp' or kind == 'bytep':
                 def _to_string(self, maxlen):

lib_pypy/cffi/vengine_cpy.py

     def patch_extension_kwds(self, kwds):
         pass
 
+    def find_module(self, module_name, path, so_suffix):
+        try:
+            f, filename, descr = imp.find_module(module_name, path)
+        except ImportError:
+            return None
+        if f is not None:
+            f.close()
+        # Note that after a setuptools installation, there are both .py
+        # and .so files with the same basename.  The code here relies on
+        # imp.find_module() locating the .so in priority.
+        if descr[0] != so_suffix:
+            return None
+        return filename
+
     def collect_types(self):
         self._typesdict = {}
         self._generate("collecttype")
         prnt('static void %s(%s *p)' % (checkfuncname, cname))
         prnt('{')
         prnt('  /* only to generate compile-time warnings or errors */')
-        for fname, ftype, _ in tp.enumfields():
+        for fname, ftype, fbitsize in tp.enumfields():
             if (isinstance(ftype, model.PrimitiveType)
-                and ftype.is_integer_type()):
+                and ftype.is_integer_type()) or fbitsize >= 0:
                 # accept all integers, but complain on float or double
                 prnt('  (void)((p->%s) << 1);' % fname)
             else:

lib_pypy/cffi/vengine_gen.py

-import sys
+import sys, os
 import types
 
 from . import model, ffiplatform
         # up in kwds['export_symbols'].
         kwds.setdefault('export_symbols', self.export_symbols)
 
+    def find_module(self, module_name, path, so_suffix):
+        basename = module_name + so_suffix
+        if path is None:
+            path = sys.path
+        for dirname in path:
+            filename = os.path.join(dirname, basename)
+            if os.path.isfile(filename):
+                return filename
+        return None
+
     def collect_types(self):
         pass      # not needed in the generic engine
 
         prnt('static void %s(%s *p)' % (checkfuncname, cname))
         prnt('{')
         prnt('  /* only to generate compile-time warnings or errors */')
-        for fname, ftype, _ in tp.enumfields():
+        for fname, ftype, fbitsize in tp.enumfields():
             if (isinstance(ftype, model.PrimitiveType)
-                and ftype.is_integer_type()):
+                and ftype.is_integer_type()) or fbitsize >= 0:
                 # accept all integers, but complain on float or double
                 prnt('  (void)((p->%s) << 1);' % fname)
             else:

lib_pypy/cffi/verifier.py

                 path = pkg.__path__
             else:
                 path = None
-            try:
-                f, filename, descr = imp.find_module(self.get_module_name(),
-                                                     path)
-            except ImportError:
+            filename = self._vengine.find_module(self.get_module_name(), path,
+                                                 _get_so_suffix())
+            if filename is None:
                 return
-            if f is not None:
-                f.close()
-            if filename.lower().endswith('.py'):
-                # on PyPy, if there are both .py and .pypy-19.so files in
-                # the same directory, the .py file is returned.  That's the
-                # case after a setuptools installation.  We never want to
-                # load the .py file here...
-                filename = filename[:-3] + _get_so_suffix()
-                if not os.path.isfile(filename):
-                    return
             self.modulefilename = filename
         self._vengine.collect_types()
         self._has_module = True

pypy/config/pypyoption.py

     del working_modules["_minimal_curses"]
     del working_modules["_posixsubprocess"]
 
-#    del working_modules["cppyy"]  # not tested on win32
+    if "cppyy" in working_modules:
+        del working_modules["cppyy"]  # not tested on win32
 
     # The _locale module is needed by site.py on Windows
     default_modules["_locale"] = None
     del working_modules["_minimal_curses"]
     del working_modules["termios"]
     del working_modules["_multiprocessing"]   # depends on rctime
-#    del working_modules["cppyy"]  # depends on ctypes
+    if "cppyy" in working_modules:
+        del working_modules["cppyy"]  # depends on ctypes
 
 
 module_dependencies = {

pypy/module/micronumpy/interp_dtype.py

         if w_fields == space.w_None:
             self.fields = None
         else:
+            self.fields = {}
             ofs_and_items = []
             size = 0
             for key in space.listview(w_fields):
     elif char == 'V':
         num = 20
         basename = 'void'
-        w_box_type = space.gettypefor(interp_boxes.W_VoidBox)
-        return dtype_from_list(space, space.newlist([]))
+        itemtype = types.VoidType(size)
+        return W_Dtype(itemtype, 20, VOIDLTR, "void" + str(size),
+                    "V", space.gettypefor(interp_boxes.W_VoidBox))
     else:
         assert char == 'U'
         basename = 'unicode'

pypy/module/micronumpy/test/test_dtypes.py

             assert a.dtype.__reduce__() == (dtype, ('i4', 0, 1), (3, '<', None, None, None, -1, -1, 0))
         assert loads(dumps(a.dtype)) == a.dtype
 
-    def test_pickle_record(self):
-        from numpypy import array, dtype
-        from cPickle import loads, dumps
-
-        d = dtype([("x", "int32"), ("y", "int32"), ("z", "int32"), ("value", float)])
-        assert d.__reduce__() == (dtype, ('V20', 0, 1), (3, '<', None, ('x', 'y', 'z', 'value'), {'y': (dtype('int32'), 4), 'x': (dtype('int32'), 0), 'z': (dtype('int32'), 8), 'value': (dtype('float64'), 12)}, 20, 1, 0))
-
-        new_d = loads(dumps(d))
-
-        assert new_d.__reduce__() == d.__reduce__()
-
 class AppTestTypes(BaseAppTestDtypes):
     def test_abstract_types(self):
         import numpypy as numpy
         assert isinstance(unicode_(3), str)
 
 class AppTestRecordDtypes(BaseNumpyAppTest):
+    spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
     def test_create(self):
         from numpypy import dtype, void
 
         assert dt.subdtype == (dtype(float), (10,))
         assert dt.base == dtype(float)
 
+    def test_pickle_record(self):
+        from numpypy import array, dtype
+        from cPickle import loads, dumps
+
+        d = dtype([("x", "int32"), ("y", "int32"), ("z", "int32"), ("value", float)])
+        assert d.__reduce__() == (dtype, ('V20', 0, 1), (3, '<', None, ('x', 'y', 'z', 'value'), {'y': (dtype('int32'), 4), 'x': (dtype('int32'), 0), 'z': (dtype('int32'), 8), 'value': (dtype('float64'), 12)}, 20, 1, 0))
+
+        new_d = loads(dumps(d))
+
+        assert new_d.__reduce__() == d.__reduce__()
+
+    def test_pickle_record_subarrays(self):
+        from numpypy import array, dtype
+        from cPickle import loads, dumps
+
+        d = dtype([("x", "int32", (3,)), ("y", "int32", (2,)), ("z", "int32", (4,)), ("value", float, (5,))])
+        new_d = loads(dumps(d))
+
+        keys = d.fields.keys()
+        keys.sort()
+        assert keys == ["value", "x", "y", "z"]
+
+        assert new_d.itemsize == d.itemsize == 76
+
 class AppTestNotDirect(BaseNumpyAppTest):
     def setup_class(cls):
         BaseNumpyAppTest.setup_class.__func__(cls)

pypy/module/test_lib_pypy/cffi_tests/backend_tests.py

         s.c = -4
         assert s.c == -4
 
+    def test_bitfield_enum(self):
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            typedef enum { AA, BB, CC } foo_e;
+            typedef struct { foo_e f:2; } foo_s;
+        """)
+        s = ffi.new("foo_s *")
+        s.f = 2
+        assert s.f == 2
+
     def test_anonymous_struct(self):
         ffi = FFI(backend=self.Backend())
         ffi.cdef("typedef struct { int a; } foo_t;")

pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py

         assert ffi.typeof("long(*)(long, long**, ...)").cname == (
             "long(*)(long, long * *, ...)")
         assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
+
+    def test_new_handle(self):
+        ffi = FFI(backend=self.Backend())
+        o = [2, 3, 4]
+        p = ffi.new_handle(o)
+        assert ffi.typeof(p) == ffi.typeof("void *")
+        assert ffi.from_handle(p) is o
+        assert ffi.from_handle(ffi.cast("char *", p)) is o
+        py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)

pypy/module/test_lib_pypy/cffi_tests/test_function.py

         assert lib.EE == -5
         assert lib.FF == -4
 
+    def test_void_star_accepts_string(self):
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""int strlen(const void *);""")
+        lib = ffi.dlopen(None)
+        res = lib.strlen(b"hello")
+        assert res == 5
+
+    def test_signed_char_star_accepts_string(self):
+        if self.Backend is CTypesBackend:
+            py.test.skip("not supported by the ctypes backend")
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""int strlen(signed char *);""")
+        lib = ffi.dlopen(None)
+        res = lib.strlen(b"hello")
+        assert res == 5
+
+    def test_unsigned_char_star_accepts_string(self):
+        if self.Backend is CTypesBackend:
+            py.test.skip("not supported by the ctypes backend")
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""int strlen(unsigned char *);""")
+        lib = ffi.dlopen(None)
+        res = lib.strlen(b"hello")
+        assert res == 5
+
     def test_missing_function(self):
         ffi = FFI(backend=self.Backend())
         ffi.cdef("""
         """)
         m = ffi.dlopen("m")
         assert not hasattr(m, 'nonexistent')
+
+    def test_wraps_from_stdlib(self):
+        import functools
+        ffi = FFI(backend=self.Backend())
+        ffi.cdef("""
+            double sin(double x);
+        """)
+        def my_decorator(f):
+            @functools.wraps(f)
+            def wrapper(*args):
+                return f(*args) + 100
+            return wrapper
+        m = ffi.dlopen("m")
+        sin100 = my_decorator(m.sin)
+        x = sin100(1.23)
+        assert x == math.sin(1.23) + 100

pypy/module/test_lib_pypy/cffi_tests/test_verify.py

     py.test.raises(OverflowError, "s.b = 4")
     assert s.b == 3
 
+def test_struct_with_bitfield_enum():
+    ffi = FFI()
+    code = """
+        typedef enum { AA, BB, CC } foo_e;
+        typedef struct { foo_e f:2; } foo_s;
+    """
+    ffi.cdef(code)
+    ffi.verify(code)
+    s = ffi.new("foo_s *")
+    s.f = 2
+    assert s.f == 2
+
 def test_unsupported_struct_with_bitfield_ellipsis():
     ffi = FFI()
     py.test.raises(NotImplementedError, ffi.cdef,

pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py

             modules = ('cffi', '_cffi_backend')
         except ImportError:
             modules = ('cffi', '_cffi_backend', 'pycparser')
+            try:
+                import ply
+            except ImportError:
+                pass
+            else:
+                modules += ('ply',)   # needed for older versions of pycparser
         for module in modules:
             target = imp.find_module(module)[1]
             os.symlink(target, os.path.join(site_packages,

rpython/config/translationoption.py

 from rpython.config.config import ChoiceOption, StrOption, Config
 from rpython.config.config import ConfigError
 from rpython.config.support import detect_number_of_processors
-from rpython.jit.backend.detect_cpu import autodetect
-from rpython.jit.backend.detect_cpu import MODEL_X86, MODEL_X86_NO_SSE2, MODEL_X86_64
 
 DEFL_INLINE_THRESHOLD = 32.4    # just enough to inline add__Int_Int()
 # and just small enough to prevend inlining of some rlist functions.
 
 DEFL_GC = "minimark"
 
-_is_x86 = autodetect() in (MODEL_X86, MODEL_X86_64, MODEL_X86_NO_SSE2)
-
-if sys.platform.startswith("linux") and _is_x86:
+if sys.platform.startswith("linux"):
     DEFL_ROOTFINDER_WITHJIT = "asmgcc"
 else:
     DEFL_ROOTFINDER_WITHJIT = "shadowstack"