Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r82136:e83d573de6df
Date: 2016-02-09 23:32 +0100
http://bitbucket.org/pypy/pypy/changeset/e83d573de6df/

Log:    import cffi 1.5.1 at rev. 5833cd037e9e

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.0
+Version: 1.5.1
 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.0"
-__version_info__ = (1, 5, 0)
+__version__ = "1.5.1"
+__version_info__ = (1, 5, 1)
 
 # 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/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -231,6 +231,12 @@
     ((got_nonpos) == (expected <= 0) &&                 \
      (got) == (unsigned long long)expected)
 
+#ifdef MS_WIN32
+# define _cffi_stdcall  __stdcall
+#else
+# define _cffi_stdcall  /* nothing */
+#endif
+
 #ifdef __cplusplus
 }
 #endif
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
@@ -1,4 +1,4 @@
-import sys, types
+import sys, sysconfig, types
 from .lock import allocate_lock
 
 try:
@@ -544,28 +544,32 @@
 
     def _apply_embedding_fix(self, kwds):
         # must include an argument like "-lpython2.7" for the compiler
+        def ensure(key, value):
+            lst = kwds.setdefault(key, [])
+            if value not in lst:
+                lst.append(value)
+        #
         if '__pypy__' in sys.builtin_module_names:
             if hasattr(sys, 'prefix'):
                 import os
-                libdir = os.path.join(sys.prefix, 'bin')
-                dirs = kwds.setdefault('library_dirs', [])
-                if libdir not in dirs:
-                    dirs.append(libdir)
+                ensure('library_dirs', os.path.join(sys.prefix, 'bin'))
             pythonlib = "pypy-c"
         else:
             if sys.platform == "win32":
                 template = "python%d%d"
-                if sys.flags.debug:
-                    template = template + '_d'
+                if hasattr(sys, 'gettotalrefcount'):
+                    template += '_d'
             else:
                 template = "python%d.%d"
+                if sysconfig.get_config_var('DEBUG_EXT'):
+                    template += sysconfig.get_config_var('DEBUG_EXT')
             pythonlib = (template %
                     (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
             if hasattr(sys, 'abiflags'):
                 pythonlib += sys.abiflags
-        libraries = kwds.setdefault('libraries', [])
-        if pythonlib not in libraries:
-            libraries.append(pythonlib)
+        ensure('libraries', pythonlib)
+        if sys.platform == "win32":
+            ensure('extra_link_args', '/MANIFEST')
 
     def set_source(self, module_name, source, source_extension='.c', **kwds):
         if hasattr(self, '_assigned_source'):
@@ -631,7 +635,7 @@
         compiled DLL.  Use '*' to force distutils' choice, suitable for
         regular CPython C API modules.  Use a file name ending in '.*'
         to ask for the system's default extension for dynamic libraries
-        (.so/.dll).
+        (.so/.dll/.dylib).
 
         The default is '*' when building a non-embedded C API extension,
         and (module_name + '.*') when building an embedded library.
@@ -695,6 +699,10 @@
         #
         self._embedding = pysource
 
+    def def_extern(self, *args, **kwds):
+        raise ValueError("ffi.def_extern() is only available on API-mode FFI "
+                         "objects")
+
 
 def _load_backend_lib(backend, name, flags):
     if name is None:
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -220,7 +220,7 @@
         self._included_declarations = set()
         self._anonymous_counter = 0
         self._structnode2type = weakref.WeakKeyDictionary()
-        self._options = None
+        self._options = {}
         self._int_constants = {}
         self._recomplete = []
         self._uses_new_feature = None
@@ -374,7 +374,7 @@
 
     def _declare_function(self, tp, quals, decl):
         tp = self._get_type_pointer(tp, quals)
-        if self._options['dllexport']:
+        if self._options.get('dllexport'):
             tag = 'dllexport_python '
         elif self._inside_extern_python:
             tag = 'extern_python '
@@ -450,7 +450,7 @@
             prevobj, prevquals = self._declarations[name]
             if prevobj is obj and prevquals == quals:
                 return
-            if not self._options['override']:
+            if not self._options.get('override'):
                 raise api.FFIError(
                     "multiple declarations of %s (for interactive usage, "
                     "try cdef(xx, override=True))" % (name,))
@@ -729,7 +729,7 @@
             if isinstance(tp, model.StructType) and tp.partial:
                 raise NotImplementedError("%s: using both bitfields and '...;'"
                                           % (tp,))
-        tp.packed = self._options['packed']
+        tp.packed = self._options.get('packed')
         if tp.completed:    # must be re-completed: it is not opaque any more
             tp.completed = 0
             self._recomplete.append(tp)
diff --git a/lib_pypy/cffi/ffiplatform.py b/lib_pypy/cffi/ffiplatform.py
--- a/lib_pypy/cffi/ffiplatform.py
+++ b/lib_pypy/cffi/ffiplatform.py
@@ -21,14 +21,12 @@
         allsources.append(os.path.normpath(src))
     return Extension(name=modname, sources=allsources, **kwds)
 
-def compile(tmpdir, ext, compiler_verbose=0, target_extension=None,
-            embedding=False):
+def compile(tmpdir, ext, compiler_verbose=0):
     """Compile a C extension module using distutils."""
 
     saved_environ = os.environ.copy()
     try:
-        outputfilename = _build(tmpdir, ext, compiler_verbose,
-                                target_extension, embedding)
+        outputfilename = _build(tmpdir, ext, compiler_verbose)
         outputfilename = os.path.abspath(outputfilename)
     finally:
         # workaround for a distutils bugs where some env vars can
@@ -38,32 +36,7 @@
                 os.environ[key] = value
     return outputfilename
 
-def _save_val(name):
-    import distutils.sysconfig
-    config_vars = distutils.sysconfig.get_config_vars()
-    return config_vars.get(name, Ellipsis)
-
-def _restore_val(name, value):
-    import distutils.sysconfig
-    config_vars = distutils.sysconfig.get_config_vars()
-    config_vars[name] = value
-    if value is Ellipsis:
-        del config_vars[name]
-
-def _win32_hack_for_embedding():
-    from distutils.msvc9compiler import MSVCCompiler
-    if not hasattr(MSVCCompiler, '_remove_visual_c_ref_CFFI_BAK'):
-        MSVCCompiler._remove_visual_c_ref_CFFI_BAK = \
-            MSVCCompiler._remove_visual_c_ref
-    MSVCCompiler._remove_visual_c_ref = lambda self,manifest_file: 
manifest_file
-
-def _win32_unhack_for_embedding():
-    from distutils.msvc9compiler import MSVCCompiler
-    MSVCCompiler._remove_visual_c_ref = \
-        MSVCCompiler._remove_visual_c_ref_CFFI_BAK
-
-def _build(tmpdir, ext, compiler_verbose=0, target_extension=None,
-           embedding=False):
+def _build(tmpdir, ext, compiler_verbose=0):
     # XXX compact but horrible :-(
     from distutils.core import Distribution
     import distutils.errors, distutils.log
@@ -76,25 +49,14 @@
     options['build_temp'] = ('ffiplatform', tmpdir)
     #
     try:
-        if sys.platform == 'win32' and embedding:
-            _win32_hack_for_embedding()
         old_level = distutils.log.set_threshold(0) or 0
-        old_SO = _save_val('SO')
-        old_EXT_SUFFIX = _save_val('EXT_SUFFIX')
         try:
-            if target_extension is not None:
-                _restore_val('SO', target_extension)
-                _restore_val('EXT_SUFFIX', target_extension)
             distutils.log.set_verbosity(compiler_verbose)
             dist.run_command('build_ext')
             cmd_obj = dist.get_command_obj('build_ext')
             [soname] = cmd_obj.get_outputs()
         finally:
             distutils.log.set_threshold(old_level)
-            _restore_val('SO', old_SO)
-            _restore_val('EXT_SUFFIX', old_EXT_SUFFIX)
-            if sys.platform == 'win32' and embedding:
-                _win32_unhack_for_embedding()
     except (distutils.errors.CompileError,
             distutils.errors.LinkError) as e:
         raise VerificationError('%s: %s' % (e.__class__.__name__, e))
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
@@ -1170,6 +1170,8 @@
         repr_arguments = ', '.join(arguments)
         repr_arguments = repr_arguments or 'void'
         name_and_arguments = '%s(%s)' % (name, repr_arguments)
+        if tp.abi == "__stdcall":
+            name_and_arguments = '_cffi_stdcall ' + name_and_arguments
         #
         def may_need_128_bits(tp):
             return (isinstance(tp, model.PrimitiveType) and
@@ -1357,6 +1359,58 @@
     parts[-1] += extension
     return os.path.join(outputdir, *parts), parts
 
+
+# Aaargh.  Distutils is not tested at all for the purpose of compiling
+# DLLs that are not extension modules.  Here are some hacks to work
+# around that, in the _patch_for_*() functions...
+
+def _patch_meth(patchlist, cls, name, new_meth):
+    old = getattr(cls, name)
+    patchlist.append((cls, name, old))
+    setattr(cls, name, new_meth)
+    return old
+
+def _unpatch_meths(patchlist):
+    for cls, name, old_meth in reversed(patchlist):
+        setattr(cls, name, old_meth)
+
+def _patch_for_embedding(patchlist):
+    if sys.platform == 'win32':
+        # we must not remove the manifest when building for embedding!
+        from distutils.msvc9compiler import MSVCCompiler
+        _patch_meth(patchlist, MSVCCompiler, '_remove_visual_c_ref',
+                    lambda self, manifest_file: manifest_file)
+
+    if sys.platform == 'darwin':
+        # we must not make a '-bundle', but a '-dynamiclib' instead
+        from distutils.ccompiler import CCompiler
+        def my_link_shared_object(self, *args, **kwds):
+            if '-bundle' in self.linker_so:
+                self.linker_so = list(self.linker_so)
+                i = self.linker_so.index('-bundle')
+                self.linker_so[i] = '-dynamiclib'
+            return old_link_shared_object(self, *args, **kwds)
+        old_link_shared_object = _patch_meth(patchlist, CCompiler,
+                                             'link_shared_object',
+                                             my_link_shared_object)
+
+def _patch_for_target(patchlist, target):
+    from distutils.command.build_ext import build_ext
+    # if 'target' is different from '*', we need to patch some internal
+    # method to just return this 'target' value, instead of having it
+    # built from module_name
+    if target.endswith('.*'):
+        target = target[:-2]
+        if sys.platform == 'win32':
+            target += '.dll'
+        elif sys.platform == 'darwin':
+            target += '.dylib'
+        else:
+            target += '.so'
+    _patch_meth(patchlist, build_ext, 'get_ext_filename',
+                lambda self, ext_name: target)
+
+
 def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
               c_file=None, source_extension='.c', extradir=None,
               compiler_verbose=1, target=None, **kwds):
@@ -1382,36 +1436,22 @@
                 target = '%s.*' % module_name
             else:
                 target = '*'
-        if target == '*':
-            target_module_name = module_name
-            target_extension = None      # use default
-        else:
-            if target.endswith('.*'):
-                target = target[:-2]
-                if sys.platform == 'win32':
-                    target += '.dll'
-                else:
-                    target += '.so'
-            # split along the first '.' (not the last one, otherwise the
-            # preceeding dots are interpreted as splitting package names)
-            index = target.find('.')
-            if index < 0:
-                raise ValueError("target argument %r should be a file name "
-                                 "containing a '.'" % (target,))
-            target_module_name = target[:index]
-            target_extension = target[index:]
         #
-        ext = ffiplatform.get_extension(ext_c_file, target_module_name, **kwds)
+        ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds)
         updated = make_c_source(ffi, module_name, preamble, c_file)
         if call_c_compiler:
+            patchlist = []
             cwd = os.getcwd()
             try:
+                if embedding:
+                    _patch_for_embedding(patchlist)
+                if target != '*':
+                    _patch_for_target(patchlist, target)
                 os.chdir(tmpdir)
-                outputfilename = ffiplatform.compile('.', ext, 
compiler_verbose,
-                                                     target_extension,
-                                                     embedding=embedding)
+                outputfilename = ffiplatform.compile('.', ext, 
compiler_verbose)
             finally:
                 os.chdir(cwd)
+                _unpatch_meths(patchlist)
             return outputfilename
         else:
             return ext, updated
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.0"
+VERSION = "1.5.1"
 
 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.0", ("This test_c.py file is for testing a version"
+assert __version__ == "1.5.1", ("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/backend_tests.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
@@ -1847,3 +1847,8 @@
             thread.start_new_thread(f, ())
         time.sleep(1.5)
         assert seen == ['init!', 'init done'] + 6 * [7]
+
+    def test_sizeof_struct_directly(self):
+        # only works with the Python FFI instances
+        ffi = FFI(backend=self.Backend())
+        assert ffi.sizeof("struct{int a;}") == ffi.sizeof("int")
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
@@ -420,3 +420,7 @@
             ]:
             x = ffi.sizeof(name)
             assert 1 <= x <= 16
+
+    def test_ffi_def_extern(self):
+        ffi = FFI()
+        py.test.raises(ValueError, ffi.def_extern)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py
@@ -92,8 +92,8 @@
     assert lib.sin(1.23) == math.sin(1.23)
 
 def _Wconversion(cdef, source, **kargs):
-    if sys.platform == 'win32':
-        py.test.skip("needs GCC or Clang")
+    if sys.platform in ('win32', 'darwin'):
+        py.test.skip("needs GCC")
     ffi = FFI()
     ffi.cdef(cdef)
     py.test.raises(VerificationError, ffi.verify, source, **kargs)
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
@@ -1714,3 +1714,33 @@
     # a case where 'onerror' is not callable
     py.test.raises(TypeError, ffi.def_extern(name='bar', onerror=42),
                    lambda x: x)
+
+def test_extern_python_stdcall():
+    ffi = FFI()
+    ffi.cdef("""
+        extern "Python" int __stdcall foo(int);
+        extern "Python" int WINAPI bar(int);
+        int (__stdcall * mycb1)(int);
+        int indirect_call(int);
+    """)
+    lib = verify(ffi, 'test_extern_python_stdcall', """
+        #ifndef _MSC_VER
+        #  define __stdcall
+        #endif
+        static int (__stdcall * mycb1)(int);
+        static int indirect_call(int x) {
+            return mycb1(x);
+        }
+    """)
+    #
+    @ffi.def_extern()
+    def foo(x):
+        return x + 42
+    @ffi.def_extern()
+    def bar(x):
+        return x + 43
+    assert lib.foo(100) == 142
+    assert lib.bar(100) == 143
+    lib.mycb1 = lib.foo
+    assert lib.mycb1(200) == 242
+    assert lib.indirect_call(300) == 342
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
@@ -72,8 +72,8 @@
     assert lib.sin(1.23) == math.sin(1.23)
 
 def _Wconversion(cdef, source, **kargs):
-    if sys.platform == 'win32':
-        py.test.skip("needs GCC or Clang")
+    if sys.platform in ('win32', 'darwin'):
+        py.test.skip("needs GCC")
     ffi = FFI()
     ffi.cdef(cdef)
     py.test.raises(VerificationError, ffi.verify, source, **kargs)
@@ -2092,20 +2092,20 @@
     old = sys.getdlopenflags()
     try:
         ffi1 = FFI()
-        ffi1.cdef("int foo_verify_dlopen_flags;")
+        ffi1.cdef("int foo_verify_dlopen_flags_1;")
         sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW)
-        lib1 = ffi1.verify("int foo_verify_dlopen_flags;")
+        lib1 = ffi1.verify("int foo_verify_dlopen_flags_1;")
     finally:
         sys.setdlopenflags(old)
 
     ffi2 = FFI()
     ffi2.cdef("int *getptr(void);")
     lib2 = ffi2.verify("""
-        extern int foo_verify_dlopen_flags;
-        static int *getptr(void) { return &foo_verify_dlopen_flags; }
+        extern int foo_verify_dlopen_flags_1;
+        static int *getptr(void) { return &foo_verify_dlopen_flags_1; }
     """)
     p = lib2.getptr()
-    assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags') == p
+    assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags_1') == p
 
 def test_consider_not_implemented_function_type():
     ffi = FFI()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
@@ -49,7 +49,8 @@
             import setuptools
         except ImportError:
             py.test.skip("setuptools not found")
-        self.run(['setup.py', 'egg_info'], cwd=self.rootdir)
+        if os.path.exists(os.path.join(self.rootdir, 'setup.py')):
+            self.run(['setup.py', 'egg_info'], cwd=self.rootdir)
         TestDist._setuptools_ready = True
 
     def check_produced_files(self, content, curdir=None):
@@ -58,7 +59,7 @@
         found_so = None
         for name in os.listdir(curdir):
             if (name.endswith('.so') or name.endswith('.pyd') or
-                name.endswith('.dylib')):
+                name.endswith('.dylib') or name.endswith('.dll')):
                 found_so = os.path.join(curdir, name)
                 # foo.so => foo
                 parts = name.split('.')
@@ -220,23 +221,6 @@
         x = ffi.compile(target="foo.bar.*")
         if sys.platform != 'win32':
             sofile = self.check_produced_files({
-                'foo.bar.SO': None,
-                'mod_name_in_package': {'mymod.c': None,
-                                        'mymod.o': None}})
-            assert os.path.isabs(x) and os.path.samefile(x, sofile)
-        else:
-            self.check_produced_files({
-                'foo.bar.SO': None,
-                'mod_name_in_package': {'mymod.c': None},
-                'Release': '?'})
-
-    @chdir_to_tmp
-    def test_api_compile_explicit_target_2(self):
-        ffi = cffi.FFI()
-        ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
-        x = ffi.compile(target=os.path.join("mod_name_in_package", 
"foo.bar.*"))
-        if sys.platform != 'win32':
-            sofile = self.check_produced_files({
                 'mod_name_in_package': {'foo.bar.SO': None,
                                         'mymod.c': None,
                                         'mymod.o': None}})
@@ -254,15 +238,16 @@
         x = ffi.compile(target="foo.bar.baz")
         if sys.platform != 'win32':
             self.check_produced_files({
-                'foo.bar.baz': None,
-                'mod_name_in_package': {'mymod.c': None,
+                'mod_name_in_package': {'foo.bar.baz': None,
+                                        'mymod.c': None,
                                         'mymod.o': None}})
-            sofile = os.path.join(str(self.udir), 'foo.bar.baz')
+            sofile = os.path.join(str(self.udir),
+                                  'mod_name_in_package', 'foo.bar.baz')
             assert os.path.isabs(x) and os.path.samefile(x, sofile)
         else:
             self.check_produced_files({
-                'foo.bar.baz': None,
-                'mod_name_in_package': {'mymod.c': None},
+                'mod_name_in_package': {'foo.bar.baz': None,
+                                        'mymod.c': None},
                 'Release': '?'})
 
     @chdir_to_tmp
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
@@ -5,10 +5,6 @@
 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
 import cffi
 
-if hasattr(sys, 'gettotalrefcount'):
-    py.test.skip("tried hard and failed to have these tests run "
-                 "in a debug-mode python")
-
 
 local_dir = os.path.dirname(os.path.abspath(__file__))
 _link_error = '?'
@@ -30,21 +26,34 @@
         py.test.skip(str(_link_error))
 
 
+def prefix_pythonpath():
+    cffi_base = os.path.dirname(os.path.dirname(local_dir))
+    pythonpath = os.environ.get('PYTHONPATH', '').split(os.pathsep)
+    if cffi_base not in pythonpath:
+        pythonpath.insert(0, cffi_base)
+    return os.pathsep.join(pythonpath)
+
+
 class EmbeddingTests:
     _compiled_modules = {}
 
     def setup_method(self, meth):
         check_lib_python_found(str(udir.ensure('embedding', dir=1)))
         self._path = udir.join('embedding', meth.__name__)
-        if sys.platform == "win32":
+        if sys.platform == "win32" or sys.platform == "darwin":
             self._compiled_modules.clear()   # workaround
 
     def get_path(self):
         return str(self._path.ensure(dir=1))
 
-    def _run(self, args, env=None):
-        print(args)
-        popen = subprocess.Popen(args, env=env, cwd=self.get_path(),
+    def _run_base(self, args, env_extra={}, **kwds):
+        print('RUNNING:', args, env_extra, kwds)
+        env = os.environ.copy()
+        env.update(env_extra)
+        return subprocess.Popen(args, env=env, **kwds)
+
+    def _run(self, args, env_extra={}):
+        popen = self._run_base(args, env_extra, cwd=self.get_path(),
                                  stdout=subprocess.PIPE,
                                  universal_newlines=True)
         output = popen.stdout.read()
@@ -65,15 +74,16 @@
             # find a solution to that: we could hack sys.path inside the
             # script run here, but we can't hack it in the same way in
             # execute().
-            env = os.environ.copy()
-            env['PYTHONPATH'] = os.path.dirname(os.path.dirname(local_dir))
+            env_extra = {'PYTHONPATH': prefix_pythonpath()}
             output = self._run([sys.executable, os.path.join(local_dir, 
filename)],
-                               env=env)
+                               env_extra=env_extra)
             match = re.compile(r"\bFILENAME: (.+)").search(output)
             assert match
             dynamic_lib_name = match.group(1)
             if sys.platform == 'win32':
                 assert dynamic_lib_name.endswith('_cffi.dll')
+            elif sys.platform == 'darwin':
+                assert dynamic_lib_name.endswith('_cffi.dylib')
             else:
                 assert dynamic_lib_name.endswith('_cffi.so')
             self._compiled_modules[name] = dynamic_lib_name
@@ -98,6 +108,7 @@
                     assert m.endswith('.dll')
                     libfiles.append('Release\\%s.lib' % m[:-4])
                 modules = libfiles
+                extra_preargs.append('/MANIFEST')
             elif threads:
                 extra_preargs.append('-pthread')
             objects = c.compile([filename], macros=sorted(defines.items()), 
debug=True)
@@ -107,21 +118,22 @@
 
     def execute(self, name):
         path = self.get_path()
-        env = os.environ.copy()
-        env['PYTHONPATH'] = os.path.dirname(os.path.dirname(local_dir))
-        libpath = env.get('LD_LIBRARY_PATH')
+        env_extra = {'PYTHONPATH': prefix_pythonpath()}
+        libpath = os.environ.get('LD_LIBRARY_PATH')
         if libpath:
             libpath = path + ':' + libpath
         else:
             libpath = path
-        env['LD_LIBRARY_PATH'] = libpath
+        env_extra['LD_LIBRARY_PATH'] = libpath
         print('running %r in %r' % (name, path))
         executable_name = name
         if sys.platform == 'win32':
             executable_name = os.path.join(path, executable_name + '.exe')
-        popen = subprocess.Popen([executable_name], cwd=path, env=env,
-                                 stdout=subprocess.PIPE,
-                                 universal_newlines=True)
+        else:
+            executable_name = os.path.join('.', executable_name)
+        popen = self._run_base([executable_name], env_extra, cwd=path,
+                               stdout=subprocess.PIPE,
+                               universal_newlines=True)
         result = popen.stdout.read()
         err = popen.wait()
         if err:
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to