Author: Ronan Lamy <[email protected]>
Branch: py3k
Changeset: r87557:fd250a74696a
Date: 2016-10-03 20:22 +0100
http://bitbucket.org/pypy/pypy/changeset/fd250a74696a/

Log:    Merged py3k-test-cpyext into py3k

diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2339,7 +2339,7 @@
         int ii, nn;
         int n = PyList_Size(obj2);
         PyObject *v = getarrayitem(obj1, 0);
-        int i = ((PyIntObject*)v)->ob_ival;
+        long i = PyLong_AsLong(v);
         PyObject * ret = PyList_New(n*i);
         for (ii = 0; ii < i; ii++)
             for (nn = 0; nn < n; nn++)
@@ -2697,8 +2697,7 @@
     PyObject_GenericGetAttr,                    /* tp_getattro */
     0,                                          /* tp_setattro */
     &array_as_buffer,                           /* tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
-    Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_CHECKTYPES,  /* tp_flags */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /* tp_flags */
     arraytype_doc,                              /* tp_doc */
     0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
@@ -2740,8 +2739,7 @@
     PyObject_GenericGetAttr,                    /* tp_getattro */
     0,                                          /* tp_setattro */
     &array_as_buffer,                           /* tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 
-    Py_TPFLAGS_HAVE_WEAKREFS | Py_TPFLAGS_CHECKTYPES,  /* tp_flags */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /* tp_flags */
     arraytype_doc,                              /* tp_doc */
     0,                                          /* tp_traverse */
     0,                                          /* tp_clear */
@@ -2888,7 +2886,7 @@
     register Py_UNICODE *p;
     struct arraydescr *descr;
 
-    ArrayBasetype.ob_type = &PyType_Type;
+    Py_TYPE(&ArrayBasetype) = &PyType_Type;
     Arraytype.tp_base = &ArrayBasetype;
     if (PyType_Ready(&Arraytype) < 0)
         return NULL;
diff --git a/pypy/module/cpyext/test/conftest.py 
b/pypy/module/cpyext/test/conftest.py
--- a/pypy/module/cpyext/test/conftest.py
+++ b/pypy/module/cpyext/test/conftest.py
@@ -3,6 +3,10 @@
 
 def pytest_configure(config):
     if config.option.runappdirect:
+        import sys
+        import py
+        from pypy import pypydir
+        sys.path.append(str(py.path.local(pypydir) / 'tool' / 'cpyext'))
         return
     from pypy.tool.pytest.objspace import gettestobjspace
     # For some reason (probably a ll2ctypes cache issue on linux64)
@@ -13,8 +17,6 @@
     space.getbuiltinmodule("time")
 
 def pytest_ignore_collect(path, config):
-    if config.option.runappdirect:
-        return True # "cannot be run by py.test -A"
     # ensure additional functions are registered
     import pypy.module.cpyext.test.test_cpyext
     return False
diff --git a/pypy/module/cpyext/test/support.py 
b/pypy/module/cpyext/test/support.py
deleted file mode 100644
--- a/pypy/module/cpyext/test/support.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import os
-import py
-from sys import platform
-
-if os.name != 'nt':
-    so_ext = 'so'
-else:
-    so_ext = 'dll'
-
-def c_compile(cfilenames, outputfilename,
-        compile_extra=None, link_extra=None,
-        include_dirs=None, libraries=None, library_dirs=None):
-    compile_extra = compile_extra or []
-    link_extra = link_extra or []
-    include_dirs = include_dirs or []
-    libraries = libraries or []
-    library_dirs = library_dirs or []
-    if platform == 'win32':
-        link_extra = link_extra + ['/DEBUG'] # generate .pdb file
-    if platform == 'darwin':
-        # support Fink & Darwinports
-        for s in ('/sw/', '/opt/local/'):
-            if (s + 'include' not in include_dirs
-                    and os.path.exists(s + 'include')):
-                include_dirs.append(s + 'include')
-            if s + 'lib' not in library_dirs and os.path.exists(s + 'lib'):
-                library_dirs.append(s + 'lib')
-
-    outputfilename = py.path.local(outputfilename).new(ext=so_ext)
-    saved_environ = os.environ.copy()
-    try:
-        _build(
-            cfilenames, outputfilename,
-            compile_extra, link_extra,
-            include_dirs, libraries, library_dirs)
-    finally:
-        # workaround for a distutils bugs where some env vars can
-        # become longer and longer every time it is used
-        for key, value in saved_environ.items():
-            if os.environ.get(key) != value:
-                os.environ[key] = value
-    return outputfilename
-
-def _build(cfilenames, outputfilename, compile_extra, link_extra,
-        include_dirs, libraries, library_dirs):
-    from distutils.ccompiler import new_compiler
-    from distutils import sysconfig
-    compiler = new_compiler(force=1)
-    sysconfig.customize_compiler(compiler) # XXX
-    objects = []
-    for cfile in cfilenames:
-        cfile = py.path.local(cfile)
-        old = cfile.dirpath().chdir()
-        try:
-            res = compiler.compile([cfile.basename],
-                include_dirs=include_dirs, extra_preargs=compile_extra)
-            assert len(res) == 1
-            cobjfile = py.path.local(res[0])
-            assert cobjfile.check()
-            objects.append(str(cobjfile))
-        finally:
-            old.chdir()
-
-    compiler.link_shared_object(
-        objects, str(outputfilename),
-        libraries=libraries,
-        extra_preargs=link_extra,
-        library_dirs=library_dirs)
diff --git a/pypy/module/cpyext/test/test_cpyext.py 
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -1,24 +1,20 @@
 import sys
 import weakref
-import os
 
-import py, pytest
+import pytest
 
-from pypy import pypydir
+from pypy.tool.cpyext.extbuild import (
+    SystemCompilationInfo, HERE, get_sys_info_app)
 from pypy.interpreter.gateway import unwrap_spec, interp2app
 from rpython.rtyper.lltypesystem import lltype, ll2ctypes
-from rpython.translator.gensupp import uniquemodulename
-from rpython.tool.udir import udir
 from pypy.module.cpyext import api
 from pypy.module.cpyext.state import State
 from pypy.module.cpyext.pyobject import Py_DecRef
 from rpython.tool.identity_dict import identity_dict
 from rpython.tool import leakfinder
 from rpython.rlib import rawrefcount
+from rpython.tool.udir import udir
 
-from .support import c_compile
-
-HERE = py.path.local(pypydir) / 'module' / 'cpyext' / 'test'
 only_pypy ="config.option.runappdirect and '__pypy__' not in 
sys.builtin_module_names"
 
 @api.cpython_api([], api.PyObject)
@@ -34,104 +30,6 @@
         assert 'PyModule_Check' in api.FUNCTIONS
         assert api.FUNCTIONS['PyModule_Check'].argtypes == [api.PyObject]
 
-def convert_sources_to_files(sources, dirname):
-    files = []
-    for i, source in enumerate(sources):
-        filename = dirname / ('source_%d.c' % i)
-        with filename.open('w') as f:
-            f.write(str(source))
-        files.append(filename)
-    return files
-
-class SystemCompilationInfo(object):
-    """Bundles all the generic information required to compile extensions.
-
-    Note: here, 'system' means OS + target interpreter + test config + ...
-    """
-    def __init__(self, include_extra=None, compile_extra=None, link_extra=None,
-            extra_libs=None, ext=None):
-        self.include_extra = include_extra or []
-        self.compile_extra = compile_extra
-        self.link_extra = link_extra
-        self.extra_libs = extra_libs
-        self.ext = ext
-
-    def compile_extension_module(self, name, include_dirs=None,
-            source_files=None, source_strings=None):
-        """
-        Build an extension module and return the filename of the resulting
-        native code file.
-
-        name is the name of the module, possibly including dots if it is a
-        module inside a package.
-
-        Any extra keyword arguments are passed on to ExternalCompilationInfo to
-        build the module (so specify your source with one of those).
-        """
-        include_dirs = include_dirs or []
-        modname = name.split('.')[-1]
-        dirname = (udir/uniquemodulename('module')).ensure(dir=1)
-        if source_strings:
-            assert not source_files
-            files = convert_sources_to_files(source_strings, dirname)
-            source_files = files
-        soname = c_compile(source_files, outputfilename=str(dirname/modname),
-            compile_extra=self.compile_extra,
-            link_extra=self.link_extra,
-            include_dirs=self.include_extra + include_dirs,
-            libraries=self.extra_libs)
-        pydname = soname.new(purebasename=modname, ext=self.ext)
-        soname.rename(pydname)
-        return str(pydname)
-
-    def import_module(self, name, init=None, body='', filename=None,
-            include_dirs=None, PY_SSIZE_T_CLEAN=False):
-        """
-        init specifies the overall template of the module.
-
-        if init is None, the module source will be loaded from a file in this
-        test directory, give a name given by the filename parameter.
-
-        if filename is None, the module name will be used to construct the
-        filename.
-        """
-        name = name.encode()
-        if body or init:
-            body = body.encode()
-            if init is None:
-                init = "return PyModule_Create(&moduledef);"
-            else:
-                init = init.encode()
-        if init is not None:
-            code = make_source(name, init, body, PY_SSIZE_T_CLEAN)
-            kwds = dict(source_strings=[code])
-        else:
-            assert not PY_SSIZE_T_CLEAN
-            if filename is None:
-                filename = name
-            filename = HERE / (filename + ".c")
-            kwds = dict(source_files=[filename])
-        mod = self.compile_extension_module(
-            name, include_dirs=include_dirs, **kwds)
-        return self.load_module(mod, name)
-
-    def import_extension(self, modname, functions, prologue="",
-            include_dirs=None, more_init="", PY_SSIZE_T_CLEAN=False):
-        body = prologue + make_methods(functions, modname)
-        init = """PyObject *mod = PyModule_Create(&moduledef);"""
-        if more_init:
-            init += more_init
-        init += "\nreturn mod;"
-        return self.import_module(
-            name=modname, init=init, body=body, include_dirs=include_dirs,
-            PY_SSIZE_T_CLEAN=PY_SSIZE_T_CLEAN)
-
-
-class ExtensionCompiler(SystemCompilationInfo):
-    """Extension compiler for appdirect mode"""
-    def load_module(space, mod, name):
-        import imp
-        return imp.load_dynamic(name, mod)
 
 class SpaceCompiler(SystemCompilationInfo):
     """Extension compiler for regular (untranslated PyPy) mode"""
@@ -167,6 +65,7 @@
         else:
             compile_extra = link_extra = None
     return SpaceCompiler(space,
+        builddir_base=udir,
         include_extra=api.include_dirs,
         compile_extra=compile_extra,
         link_extra=link_extra,
@@ -174,81 +73,6 @@
         ext=get_so_extension(space))
 
 
-def get_so_suffix():
-    from imp import get_suffixes, C_EXTENSION
-    for suffix, mode, typ in get_suffixes():
-        if typ == C_EXTENSION:
-            return suffix
-    else:
-        raise RuntimeError("This interpreter does not define a filename "
-            "suffix for C extensions!")
-
-def get_sys_info_app():
-    from distutils.sysconfig import get_python_inc
-    if sys.platform == 'win32':
-        compile_extra = ["/we4013"]
-        link_extra = ["/LIBPATH:" + os.path.join(sys.exec_prefix, 'libs')]
-    elif sys.platform == 'darwin':
-        compile_extra = link_extra = None
-        pass
-    elif sys.platform.startswith('linux'):
-        compile_extra = [
-            "-O0", "-g", "-Werror=implicit-function-declaration", "-fPIC"]
-        link_extra = None
-    ext = get_so_suffix()
-    return ExtensionCompiler(
-        include_extra=[get_python_inc()],
-        compile_extra=compile_extra,
-        link_extra=link_extra,
-        ext=get_so_suffix())
-
-def make_methods(functions, modname):
-    methods_table = []
-    codes = []
-    for funcname, flags, code in functions:
-        cfuncname = "%s_%s" % (modname, funcname)
-        methods_table.append("{\"%s\", %s, %s}," %
-                                (funcname, cfuncname, flags))
-        func_code = """
-        static PyObject* %s(PyObject* self, PyObject* args)
-        {
-        %s
-        }
-        """ % (cfuncname, code)
-        codes.append(func_code)
-
-    body = "\n".join(codes) + """
-    static PyMethodDef methods[] = {
-    %(methods)s
-    { NULL }
-    };
-    static struct PyModuleDef moduledef = {
-        PyModuleDef_HEAD_INIT,
-        "%(modname)s",  /* m_name */
-        NULL,           /* m_doc */
-        -1,             /* m_size */
-        methods,        /* m_methods */
-    };
-    """ % dict(methods='\n'.join(methods_table), modname=modname)
-    return body
-
-def make_source(name, init, body, PY_SSIZE_T_CLEAN):
-    code = """
-    %(PY_SSIZE_T_CLEAN)s
-    #include <Python.h>
-
-    %(body)s
-
-    PyMODINIT_FUNC
-    PyInit_%(name)s(void) {
-    %(init)s
-    }
-    """ % dict(name=name, init=init, body=body,
-            PY_SSIZE_T_CLEAN='#define PY_SSIZE_T_CLEAN'
-                if PY_SSIZE_T_CLEAN else '')
-    return code
-
-
 def freeze_refcnts(self):
     rawrefcount._dont_free_any_more()
     return #ZZZ
@@ -261,7 +85,7 @@
 
 class LeakCheckingTest(object):
     """Base class for all cpyext tests."""
-    spaceconfig = dict(usemodules=['cpyext', 'thread', '_rawffi', 'array',
+    spaceconfig = dict(usemodules=['cpyext', 'thread', 'struct', 'array',
                                    'itertools', 'time', 'binascii',
                                    ])
 
@@ -392,18 +216,14 @@
 def debug_collect(space):
     rawrefcount._collect()
 
-def gc_collect3(space):
-    import gc
-    gc.collect()
-    gc.collect()
-    gc.collect()
-
 class AppTestCpythonExtensionBase(LeakCheckingTest):
 
     def setup_class(cls):
         space = cls.space
         cls.w_here = space.wrap(str(HERE))
+        cls.w_udir = space.wrap(str(udir))
         if not cls.runappdirect:
+            cls.sys_info = get_cpyext_info(space)
             cls.w_runappdirect = space.wrap(cls.runappdirect)
             space.getbuiltinmodule("cpyext")
             # 'import os' to warm up reference counts
@@ -413,7 +233,40 @@
             #state.non_heaptypes_w[:] = []
             cls.w_debug_collect = space.wrap(interp2app(debug_collect))
         else:
-            cls.debug_collect = gc_collect3
+            def w_import_module(self, name, init=None, body='', filename=None,
+                    include_dirs=None, PY_SSIZE_T_CLEAN=False):
+                from extbuild import get_sys_info_app
+                sys_info = get_sys_info_app(self.udir)
+                return sys_info.import_module(
+                    name, init=init, body=body, filename=filename,
+                    include_dirs=include_dirs,
+                    PY_SSIZE_T_CLEAN=PY_SSIZE_T_CLEAN)
+            cls.w_import_module = w_import_module
+
+            def w_import_extension(self, modname, functions, prologue="",
+                include_dirs=None, more_init="", PY_SSIZE_T_CLEAN=False):
+                from extbuild import get_sys_info_app
+                sys_info = get_sys_info_app(self.udir)
+                return sys_info.import_extension(
+                    modname, functions, prologue=prologue,
+                    include_dirs=include_dirs, more_init=more_init,
+                    PY_SSIZE_T_CLEAN=PY_SSIZE_T_CLEAN)
+            cls.w_import_extension = w_import_extension
+
+            def w_compile_module(self, name,
+                    source_files=None, source_strings=None):
+                from extbuild import get_sys_info_app
+                sys_info = get_sys_info_app(self.udir)
+                return sys_info.compile_extension_module(name,
+                    source_files=source_files, source_strings=source_strings)
+            cls.w_compile_module = w_compile_module
+
+            def w_load_module(self, mod, name):
+                from extbuild import get_sys_info_app
+                sys_info = get_sys_info_app(self.udir)
+                return sys_info.load_module(mod, name)
+            cls.w_load_module = w_load_module
+
 
     def record_imported_module(self, name):
         """
@@ -425,6 +278,9 @@
         self.imported_module_names.append(name)
 
     def setup_method(self, func):
+        if self.runappdirect:
+            return
+
         @unwrap_spec(name=str)
         def compile_module(space, name,
                            w_source_files=None,
@@ -483,25 +339,17 @@
         # self.space).  These will be cleaned up automatically in teardown.
         self.imported_module_names = []
 
-        if self.runappdirect:
-            self.sys_info = get_sys_info_app()
-            self.compile_module = self.sys_info.compile_extension_module
-            self.load_module = self.sys_info.load_module
-            self.import_module = self.sys_info.import_module
-            self.import_extension = self.sys_info.import_extension
-        else:
-            wrap = self.space.wrap
-            self.sys_info = get_cpyext_info(self.space)
-            self.w_compile_module = wrap(interp2app(compile_module))
-            self.w_load_module = wrap(interp2app(load_module))
-            self.w_import_module = wrap(interp2app(import_module))
-            self.w_import_extension = wrap(interp2app(import_extension))
+        wrap = self.space.wrap
+        self.w_compile_module = wrap(interp2app(compile_module))
+        self.w_load_module = wrap(interp2app(load_module))
+        self.w_import_module = wrap(interp2app(import_module))
+        self.w_import_extension = wrap(interp2app(import_extension))
 
-            # create the file lock before we count allocations
-            self.space.call_method(self.space.sys.get("stdout"), "flush")
+        # create the file lock before we count allocations
+        self.space.call_method(self.space.sys.get("stdout"), "flush")
 
-            freeze_refcnts(self)
-            #self.check_and_print_leaks()
+        freeze_refcnts(self)
+        #self.check_and_print_leaks()
 
     def unimport_module(self, name):
         """
diff --git a/pypy/tool/cpyext/__init__.py b/pypy/tool/cpyext/__init__.py
new file mode 100644
--- /dev/null
+++ b/pypy/tool/cpyext/__init__.py
@@ -0,0 +1,4 @@
+"""
+Support code for pypy/module/cpyext/test/. This is here so that it can be
+imported by Python3 when running -A tests.
+"""
diff --git a/pypy/tool/cpyext/extbuild.py b/pypy/tool/cpyext/extbuild.py
new file mode 100644
--- /dev/null
+++ b/pypy/tool/cpyext/extbuild.py
@@ -0,0 +1,247 @@
+import os
+import sys
+import py
+from pypy import pypydir
+
+if os.name != 'nt':
+    so_ext = 'so'
+else:
+    so_ext = 'dll'
+
+HERE = py.path.local(pypydir) / 'module' / 'cpyext' / 'test'
+
+class SystemCompilationInfo(object):
+    """Bundles all the generic information required to compile extensions.
+
+    Note: here, 'system' means OS + target interpreter + test config + ...
+    """
+    def __init__(self, builddir_base, include_extra=None, compile_extra=None,
+            link_extra=None, extra_libs=None, ext=None):
+        self.builddir_base = builddir_base
+        self.include_extra = include_extra or []
+        self.compile_extra = compile_extra
+        self.link_extra = link_extra
+        self.extra_libs = extra_libs
+        self.ext = ext
+
+    def get_builddir(self, name):
+        builddir = py.path.local.make_numbered_dir(
+            rootdir=py.path.local(self.builddir_base),
+            prefix=name + '-',
+            keep=0)  # keep everything
+        return builddir
+
+    def compile_extension_module(self, name, include_dirs=None,
+            source_files=None, source_strings=None):
+        """
+        Build an extension module and return the filename of the resulting
+        native code file.
+
+        name is the name of the module, possibly including dots if it is a
+        module inside a package.
+        """
+        include_dirs = include_dirs or []
+        modname = name.split('.')[-1]
+        dirname = self.get_builddir(name=modname)
+        if source_strings:
+            assert not source_files
+            files = convert_sources_to_files(source_strings, dirname)
+            source_files = files
+        soname = c_compile(source_files, outputfilename=str(dirname / modname),
+            compile_extra=self.compile_extra,
+            link_extra=self.link_extra,
+            include_dirs=self.include_extra + include_dirs,
+            libraries=self.extra_libs)
+        pydname = soname.new(purebasename=modname, ext=self.ext)
+        soname.rename(pydname)
+        return str(pydname)
+
+    def import_module(self, name, init=None, body='', filename=None,
+            include_dirs=None, PY_SSIZE_T_CLEAN=False):
+        """
+        init specifies the overall template of the module.
+
+        if init is None, the module source will be loaded from a file in this
+        test directory, give a name given by the filename parameter.
+
+        if filename is None, the module name will be used to construct the
+        filename.
+        """
+        if body or init:
+            if init is None:
+                init = "return PyModule_Create(&moduledef);"
+        if init is not None:
+            code = make_source(name, init, body, PY_SSIZE_T_CLEAN)
+            kwds = dict(source_strings=[code])
+        else:
+            assert not PY_SSIZE_T_CLEAN
+            if filename is None:
+                filename = name
+            filename = HERE / (filename + ".c")
+            kwds = dict(source_files=[filename])
+        mod = self.compile_extension_module(
+            name, include_dirs=include_dirs, **kwds)
+        return self.load_module(mod, name)
+
+    def import_extension(self, modname, functions, prologue="",
+            include_dirs=None, more_init="", PY_SSIZE_T_CLEAN=False):
+        body = prologue + make_methods(functions, modname)
+        init = """PyObject *mod = PyModule_Create(&moduledef);"""
+        if more_init:
+            init += more_init
+        init += "\nreturn mod;"
+        return self.import_module(
+            name=modname, init=init, body=body, include_dirs=include_dirs,
+            PY_SSIZE_T_CLEAN=PY_SSIZE_T_CLEAN)
+
+class ExtensionCompiler(SystemCompilationInfo):
+    """Extension compiler for appdirect mode"""
+    def load_module(space, mod, name):
+        import imp
+        return imp.load_dynamic(name, mod)
+
+def convert_sources_to_files(sources, dirname):
+    files = []
+    for i, source in enumerate(sources):
+        filename = dirname / ('source_%d.c' % i)
+        with filename.open('w') as f:
+            f.write(str(source))
+        files.append(filename)
+    return files
+
+
+def make_methods(functions, modname):
+    methods_table = []
+    codes = []
+    for funcname, flags, code in functions:
+        cfuncname = "%s_%s" % (modname, funcname)
+        methods_table.append("{\"%s\", %s, %s}," %
+                                (funcname, cfuncname, flags))
+        func_code = """
+        static PyObject* %s(PyObject* self, PyObject* args)
+        {
+        %s
+        }
+        """ % (cfuncname, code)
+        codes.append(func_code)
+
+    body = "\n".join(codes) + """
+    static PyMethodDef methods[] = {
+    %(methods)s
+    { NULL }
+    };
+    static struct PyModuleDef moduledef = {
+        PyModuleDef_HEAD_INIT,
+        "%(modname)s",  /* m_name */
+        NULL,           /* m_doc */
+        -1,             /* m_size */
+        methods,        /* m_methods */
+    };
+    """ % dict(methods='\n'.join(methods_table), modname=modname)
+    return body
+
+def make_source(name, init, body, PY_SSIZE_T_CLEAN):
+    code = """
+    %(PY_SSIZE_T_CLEAN)s
+    #include <Python.h>
+
+    %(body)s
+
+    PyMODINIT_FUNC
+    PyInit_%(name)s(void) {
+    %(init)s
+    }
+    """ % dict(
+        name=name, init=init, body=body,
+        PY_SSIZE_T_CLEAN='#define PY_SSIZE_T_CLEAN'
+            if PY_SSIZE_T_CLEAN else '')
+    return code
+
+
+def c_compile(cfilenames, outputfilename,
+        compile_extra=None, link_extra=None,
+        include_dirs=None, libraries=None, library_dirs=None):
+    compile_extra = compile_extra or []
+    link_extra = link_extra or []
+    include_dirs = include_dirs or []
+    libraries = libraries or []
+    library_dirs = library_dirs or []
+    if sys.platform == 'win32':
+        link_extra = link_extra + ['/DEBUG']  # generate .pdb file
+    if sys.platform == 'darwin':
+        # support Fink & Darwinports
+        for s in ('/sw/', '/opt/local/'):
+            if (s + 'include' not in include_dirs
+                    and os.path.exists(s + 'include')):
+                include_dirs.append(s + 'include')
+            if s + 'lib' not in library_dirs and os.path.exists(s + 'lib'):
+                library_dirs.append(s + 'lib')
+
+    outputfilename = py.path.local(outputfilename).new(ext=so_ext)
+    saved_environ = os.environ.copy()
+    try:
+        _build(
+            cfilenames, outputfilename,
+            compile_extra, link_extra,
+            include_dirs, libraries, library_dirs)
+    finally:
+        # workaround for a distutils bugs where some env vars can
+        # become longer and longer every time it is used
+        for key, value in saved_environ.items():
+            if os.environ.get(key) != value:
+                os.environ[key] = value
+    return outputfilename
+
+def _build(cfilenames, outputfilename, compile_extra, link_extra,
+        include_dirs, libraries, library_dirs):
+    from distutils.ccompiler import new_compiler
+    from distutils import sysconfig
+    compiler = new_compiler(force=1)
+    sysconfig.customize_compiler(compiler)  # XXX
+    objects = []
+    for cfile in cfilenames:
+        cfile = py.path.local(cfile)
+        old = cfile.dirpath().chdir()
+        try:
+            res = compiler.compile([cfile.basename],
+                include_dirs=include_dirs, extra_preargs=compile_extra)
+            assert len(res) == 1
+            cobjfile = py.path.local(res[0])
+            assert cobjfile.check()
+            objects.append(str(cobjfile))
+        finally:
+            old.chdir()
+
+    compiler.link_shared_object(
+        objects, str(outputfilename),
+        libraries=libraries,
+        extra_preargs=link_extra,
+        library_dirs=library_dirs)
+
+def get_so_suffix():
+    from imp import get_suffixes, C_EXTENSION
+    for suffix, mode, typ in get_suffixes():
+        if typ == C_EXTENSION:
+            return suffix
+    else:
+        raise RuntimeError("This interpreter does not define a filename "
+            "suffix for C extensions!")
+
+def get_sys_info_app(base_dir):
+    from distutils.sysconfig import get_python_inc
+    if sys.platform == 'win32':
+        compile_extra = ["/we4013"]
+        link_extra = ["/LIBPATH:" + os.path.join(sys.exec_prefix, 'libs')]
+    elif sys.platform == 'darwin':
+        compile_extra = link_extra = None
+        pass
+    elif sys.platform.startswith('linux'):
+        compile_extra = [
+            "-O0", "-g", "-Werror=implicit-function-declaration", "-fPIC"]
+        link_extra = None
+    return ExtensionCompiler(
+        builddir_base=base_dir,
+        include_extra=[get_python_inc()],
+        compile_extra=compile_extra,
+        link_extra=link_extra,
+        ext=get_so_suffix())
diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py
--- a/pypy/tool/pytest/apptest.py
+++ b/pypy/tool/pytest/apptest.py
@@ -172,8 +172,11 @@
         f.write('def %s():\n' % target_name)
         f.write('\n'.join(source))
         f.write("\n%s()\n" % target_name)
+    helper_dir = os.path.join(pypydir, 'tool', 'cpyext')
+    env = os.environ.copy()
+    env['PYTHONPATH'] = helper_dir
     res, stdout, stderr = runsubprocess.run_subprocess(
-        python_, [str(pyfile)])
+        python_, [str(pyfile)], env=env)
     print pyfile.read()
     print >> sys.stdout, stdout
     print >> sys.stderr, stderr
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to