Commits

Amaury Forgeot d'Arc committed 206365a

Fixes for cpyext module: use space.applevel instead of wrapping everything

Comments (0)

Files changed (8)

pypy/module/cpyext/state.py

         from pypy.module.cpyext.api import INIT_FUNCTIONS
 
         setup_new_method_def(space)
-        if not we_are_translated():
-            space.setattr(space.wrap(self),
-                          space.wrap('api_lib'),
-                          space.wrap(self.api_lib))
-        else:
+        if we_are_translated():
             refcountstate = space.fromcache(RefcountState)
             refcountstate.init_r2w_from_w2r()
 

pypy/module/cpyext/test/test_cpyext.py

 import py
 
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.rpython.lltypesystem import rffi, lltype, ll2ctypes
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator import platform
         assert 'PyModule_Check' in api.FUNCTIONS
         assert api.FUNCTIONS['PyModule_Check'].argtypes == [api.PyObject]
 
-def compile_module(space, modname, **kwds):
+def compile_extension_module(space, modname, **kwds):
     """
     Build an extension module and return the filename of the resulting native
     code file.
     Any extra keyword arguments are passed on to ExternalCompilationInfo to
     build the module (so specify your source with one of those).
     """
+    state = space.fromcache(State)
+    api_library = state.api_lib
+    if sys.platform == 'win32':
+        kwds["libraries"] = [api_library]
+        # '%s' undefined; assuming extern returning int
+        kwds["compile_extra"] = ["/we4013"]
+    else:
+        kwds["link_files"] = [str(api_library + '.so')]
+        if sys.platform.startswith('linux'):
+            kwds["compile_extra"]=["-Werror=implicit-function-declaration"]
+
     modname = modname.split('.')[-1]
     eci = ExternalCompilationInfo(
         export_symbols=['init%s' % (modname,)],
 class LeakCheckingTest(object):
     """Base class for all cpyext tests."""
     spaceconfig = dict(usemodules=['cpyext', 'thread', '_rawffi', 'array',
-                                   'itertools'])
+                                   'itertools', 'rctime', 'binascii'])
     enable_leak_checking = True
 
     @staticmethod
         state = cls.space.fromcache(RefcountState)
         state.non_heaptypes_w[:] = []
 
-    def compile_module(self, name, **kwds):
-        """
-        Build an extension module linked against the cpyext api library.
-        """
-        state = self.space.fromcache(State)
-        api_library = state.api_lib
-        if sys.platform == 'win32':
-            kwds["libraries"] = [api_library]
-            # '%s' undefined; assuming extern returning int
-            kwds["compile_extra"] = ["/we4013"]
-        else:
-            kwds["link_files"] = [str(api_library + '.so')]
-            if sys.platform.startswith('linux'):
-                kwds["compile_extra"]=["-Werror=implicit-function-declaration"]
-        return compile_module(self.space, name, **kwds)
+    def setup_method(self, func):
+        @unwrap_spec(name=str)
+        def compile_module(space, name,
+                           w_separate_module_files=None,
+                           w_separate_module_sources=None):
+            """
+            Build an extension module linked against the cpyext api library.
+            """
+            if not space.is_none(w_separate_module_files):
+                separate_module_files = space.listview_str(w_separate_module_files)
+                assert separate_module_files is not None
+            else:
+                separate_module_files = []
+            if not space.is_none(w_separate_module_sources):
+                separate_module_sources = space.listview_str(w_separate_module_sources)
+                assert separate_module_sources is not None
+            else:
+                separate_module_sources = []
+            pydname = compile_extension_module(
+                space, name,
+                separate_module_files=separate_module_files,
+                separate_module_sources=separate_module_sources)
+            return space.wrap(pydname)
 
+        @unwrap_spec(name=str, init='str_or_None', body=str,
+                     load_it=bool, filename='str_or_None')
+        def import_module(space, name, init=None, body='',
+                          load_it=True, filename=None):
+            """
+            init specifies the overall template of the module.
 
-    def import_module(self, name, init=None, body='', load_it=True, filename=None):
-        """
-        init specifies the overall template of the module.
+            if init is None, the module source will be loaded from a file in this
+            test direcory, give a name given by the filename parameter.
 
-        if init is None, the module source will be loaded from a file in this
-        test direcory, give a name given by the filename parameter.
+            if filename is None, the module name will be used to construct the
+            filename.
+            """
+            if init is not None:
+                code = """
+                #include <Python.h>
+                %(body)s
 
-        if filename is None, the module name will be used to construct the
-        filename.
-        """
-        if init is not None:
-            code = """
-            #include <Python.h>
-            %(body)s
+                void init%(name)s(void) {
+                %(init)s
+                }
+                """ % dict(name=name, init=init, body=body)
+                kwds = dict(separate_module_sources=[code])
+            else:
+                if filename is None:
+                    filename = name
+                filename = py.path.local(autopath.pypydir) / 'module' \
+                        / 'cpyext'/ 'test' / (filename + ".c")
+                kwds = dict(separate_module_files=[filename])
 
-            void init%(name)s(void) {
-            %(init)s
-            }
-            """ % dict(name=name, init=init, body=body)
-            kwds = dict(separate_module_sources=[code])
-        else:
-            if filename is None:
-                filename = name
-            filename = py.path.local(autopath.pypydir) / 'module' \
-                    / 'cpyext'/ 'test' / (filename + ".c")
-            kwds = dict(separate_module_files=[filename])
+            mod = compile_extension_module(space, name, **kwds)
 
-        mod = self.compile_module(name, **kwds)
+            if load_it:
+                api.load_extension_module(space, mod, name)
+                self.imported_module_names.append(name)
+                return space.getitem(
+                    space.sys.get('modules'),
+                    space.wrap(name))
+            else:
+                return os.path.dirname(mod)
 
-        if load_it:
-            api.load_extension_module(self.space, mod, name)
+        @unwrap_spec(mod=str, name=str)
+        def reimport_module(space, mod, name):
+            api.load_extension_module(space, mod, name)
+            return space.getitem(
+                space.sys.get('modules'),
+                space.wrap(name))
+
+        @unwrap_spec(modname=str, prologue=str)
+        def import_extension(space, modname, w_functions, prologue=""):
+            functions = space.unwrap(w_functions)
+            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 = prologue + "\n".join(codes) + """
+            static PyMethodDef methods[] = {
+            %s
+            { NULL }
+            };
+            """ % ('\n'.join(methods_table),)
+            init = """Py_InitModule("%s", methods);""" % (modname,)
+            return import_module(space, name=modname, init=init, body=body)
+
+        @unwrap_spec(name=str)
+        def record_imported_module(name):
+            """
+            Record a module imported in a test so that it can be cleaned up in
+            teardown before the check for leaks is done.
+
+            name gives the name of the module in the space's sys.modules.
+            """
             self.imported_module_names.append(name)
-            return self.space.getitem(
-                self.space.sys.get('modules'),
-                self.space.wrap(name))
-        else:
-            return os.path.dirname(mod)
 
-    def reimport_module(self, mod, name):
-        api.load_extension_module(self.space, mod, name)
-        return self.space.getitem(
-            self.space.sys.get('modules'),
-            self.space.wrap(name))
-
-    def import_extension(self, modname, functions, prologue=""):
-        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 = prologue + "\n".join(codes) + """
-        static PyMethodDef methods[] = {
-        %s
-        { NULL }
-        };
-        """ % ('\n'.join(methods_table),)
-        init = """Py_InitModule("%s", methods);""" % (modname,)
-        return self.import_module(name=modname, init=init, body=body)
-
-    def record_imported_module(self, name):
-        """
-        Record a module imported in a test so that it can be cleaned up in
-        teardown before the check for leaks is done.
-
-        name gives the name of the module in the space's sys.modules.
-        """
-        self.imported_module_names.append(name)
-
-    def setup_method(self, func):
         # A list of modules which the test caused to be imported (in
         # self.space).  These will be cleaned up automatically in teardown.
         self.imported_module_names = []
 
-        self.w_import_module = self.space.wrap(self.import_module)
-        self.w_reimport_module = self.space.wrap(self.reimport_module)
-        self.w_import_extension = self.space.wrap(self.import_extension)
-        self.w_compile_module = self.space.wrap(self.compile_module)
+        self.w_compile_module = self.space.wrap(interp2app(compile_module))
+        self.w_import_module = self.space.wrap(interp2app(import_module))
+        self.w_reimport_module = self.space.wrap(interp2app(reimport_module))
+        self.w_import_extension = self.space.wrap(interp2app(import_extension))
         self.w_record_imported_module = self.space.wrap(
-            self.record_imported_module)
+            interp2app(record_imported_module))
         self.w_here = self.space.wrap(
             str(py.path.local(autopath.pypydir)) + '/module/cpyext/test/')
 

pypy/module/cpyext/test/test_datetime.py

             ("get_types", "METH_NOARGS",
              """
                  PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
                  return PyTuple_Pack(4,
                                      PyDateTimeAPI->DateType,
                                      PyDateTimeAPI->DateTimeType,

pypy/module/cpyext/test/test_floatobject.py

         assert space.type(api.PyNumber_Float(space.wrap(3))) is space.w_float
         assert space.type(api.PyNumber_Float(space.wrap("3"))) is space.w_float
 
-        class Coerce(object):
-            def __float__(self):
-                return 42.5
-        assert space.eq_w(api.PyNumber_Float(space.wrap(Coerce())),
-                          space.wrap(42.5))
+        w_obj = space.appexec([], """():
+            class Coerce(object):
+                def __float__(self):
+                    return 42.5
+            return Coerce()""")
+        assert space.eq_w(api.PyNumber_Float(w_obj), space.wrap(42.5))
 
     def test_unpack(self, space, api):
         with rffi.scoped_str2charp("\x9a\x99\x99?") as ptr:

pypy/module/cpyext/test/test_intobject.py

                 == 10**30 % (2**64))
 
     def test_coerce(self, space, api):
-        class Coerce(object):
-            def __int__(self):
-                return 42
-        assert api.PyInt_AsLong(space.wrap(Coerce())) == 42
+        w_obj = space.appexec([], """():
+            class Coerce(object):
+                def __int__(self):
+                    return 42
+            return Coerce()""")
+        assert api.PyInt_AsLong(w_obj) == 42
 
 class AppTestIntObject(AppTestCpythonExtensionBase):
     def test_fromstring(self):

pypy/module/cpyext/test/test_iterator.py

 
 class TestIterator(BaseApiTest):
     def test_check_iter(self, space, api):
-        assert api.PyIter_Check(space.wrap(iter("a")))
-        assert api.PyIter_Check(space.wrap(iter([])))
-        assert not api.PyIter_Check(space.wrap(type))
+        assert api.PyIter_Check(space.iter(space.wrap("a")))
+        assert api.PyIter_Check(space.iter(space.newlist([])))
+        assert not api.PyIter_Check(space.w_type)
         assert not api.PyIter_Check(space.wrap(2))
 
     def test_getIter(self, space, api):

pypy/module/cpyext/test/test_object.py

         assert api.PyObject_Not(space.wrap(3.14)) == 0
 
     def test_exception(self, space, api):
-        class C:
-            def __nonzero__(self):
-                raise ValueError
+        w_obj = space.appexec([], """():
+            class C:
+                def __nonzero__(self):
+                    raise ValueError
+            return C()""")
 
-        assert api.PyObject_IsTrue(space.wrap(C())) == -1
-        assert api.PyObject_Not(space.wrap(C())) == -1
+        assert api.PyObject_IsTrue(w_obj) == -1
+        assert api.PyObject_Not(w_obj) == -1
         api.PyErr_Clear()
 
     def test_HasAttr(self, space, api):
         rffi.free_charp(buf)
 
     def test_SetAttr(self, space, api):
-        class X:
-            pass
-        x = X()
-        api.PyObject_SetAttr(space.wrap(x), space.wrap('test'), space.wrap(5))
+        w_obj = space.appexec([], """():
+            class C:
+                pass
+            return C()""")
+
+        api.PyObject_SetAttr(w_obj, space.wrap('test'), space.wrap(5))
         assert not api.PyErr_Occurred()
-        assert x.test == 5
-        assert api.PyObject_HasAttr(space.wrap(x), space.wrap('test'))
-        api.PyObject_SetAttr(space.wrap(x), space.wrap('test'), space.wrap(10))
-        assert x.test == 10
+        assert space.unwrap(space.getattr(w_obj, space.wrap('test'))) == 5
+        assert api.PyObject_HasAttr(w_obj, space.wrap('test'))
+        api.PyObject_SetAttr(w_obj, space.wrap('test'), space.wrap(10))
+        assert space.unwrap(space.getattr(w_obj, space.wrap('test'))) == 10
 
         buf = rffi.str2charp('test')
-        api.PyObject_SetAttrString(space.wrap(x), buf, space.wrap(20))
+        api.PyObject_SetAttrString(w_obj, buf, space.wrap(20))
         rffi.free_charp(buf)
-        assert x.test == 20
+        assert space.unwrap(space.getattr(w_obj, space.wrap('test'))) == 20
 
     def test_getattr(self, space, api):
         charp1 = rffi.str2charp("__len__")

pypy/module/cpyext/test/test_sequence.py

         assert api.PyErr_Occurred() is space.w_ValueError
         api.PyErr_Clear()
 
-        gen = (x ** 2 for x in range(40))
+        w_gen = space.appexec([], """():
+           return (x ** 2 for x in range(40))""")
         w_tofind = space.wrap(16)
-        result = api.PySequence_Index(space.wrap(gen), w_tofind)
+        result = api.PySequence_Index(w_gen, w_tofind)
         assert result == 4
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.