[pypy-svn] commit/pypy: arigo: Merge 'cpyext-2.5-backport', backporting the cpyext module from fast-forward.

Bitbucket commits-noreply at bitbucket.org
Sun Dec 19 14:46:05 CET 2010


1 new changeset in pypy:

http://bitbucket.org/pypy/pypy/changeset/2a2c37092960/
changeset:   r40129:2a2c37092960
user:        arigo
date:        2010-12-19 14:45:54
summary:     Merge 'cpyext-2.5-backport', backporting the cpyext module from fast-forward.
affected #:  15 files (3.7 KB)

--- a/.hgignore	Sun Dec 19 13:09:34 2010 +0100
+++ b/.hgignore	Sun Dec 19 14:45:54 2010 +0100
@@ -1,50 +1,51 @@
-syntax:glob
+syntax: glob
 *.py[co]
 *~
 
-testresult
-site-packages
-pypy/module/cpyext/src/*.o
-pypy/bin/pypy-c
-pypy/translator/jvm/src/pypy/*.class
-pypy/module/cpyext/test/*.errors
-pypy/doc/*.html
-pypy/doc/basicblock.asc
-pypy/doc/*.svninfo
-pypy/translator/jvm/.project
-pypy/translator/jvm/.classpath
-pypy/translator/jvm/eclipse-bin
-pypy/translator/benchmark/docutils
-pypy/translator/benchmark/templess
-pypy/translator/benchmark/gadfly
-pypy/translator/benchmark/mako
-pypy/translator/benchmark/bench-custom.benchmark_result
-pypy/translator/benchmark/shootout_benchmarks
-pypy/translator/goal/pypy-translation-snapshot
-pypy/translator/goal/pypy-c*
-pypy/translator/goal/*.exe
-pypy/translator/goal/target*-c
-pypy/_cache
-site-packages/*.egg
-site-packages/*.pth
-pypy/doc/statistic/*.html
-pypy/doc/statistic/*.eps
-pypy/doc/statistic/*.pdf
-pypy/translator/cli/src/pypylib.dll
-pypy/translator/cli/src/query.exe
-pypy/translator/cli/src/main.exe
-lib_pypy/ctypes_config_cache/_*_cache.py
-lib_pypy/ctypes_config_cache/_*_*_.py
-pypy/translator/cli/query-descriptions
-pypy/doc/discussion/*.html
-include/*.h
-include/*.inl
-pypy/doc/config/*.html
-pypy/doc/config/style.css
-pypy/doc/jit/*.html
-pypy/doc/jit/style.css
-pypy/doc/image/lattice1.png
-pypy/doc/image/lattice2.png
-pypy/doc/image/lattice3.png
-pypy/doc/image/stackless_informal.png
-pypy/doc/image/parsing_example*.png
+syntax: regexp
+^testresult$
+^site-packages$
+^pypy/module/cpyext/src/.+\.o$
+^pypy/bin/pypy-c
+^pypy/translator/jvm/src/pypy/.+\.class$
+^pypy/module/cpyext/test/.+\.errors$
+^pypy/doc/.+\.html$
+^pypy/doc/basicblock\.asc$
+^pypy/doc/.+\.svninfo$
+^pypy/translator/jvm/\.project$
+^pypy/translator/jvm/\.classpath$
+^pypy/translator/jvm/eclipse-bin$
+^pypy/translator/benchmark/docutils$
+^pypy/translator/benchmark/templess$
+^pypy/translator/benchmark/gadfly$
+^pypy/translator/benchmark/mako$
+^pypy/translator/benchmark/bench-custom\.benchmark_result$
+^pypy/translator/benchmark/shootout_benchmarks$
+^pypy/translator/goal/pypy-translation-snapshot$
+^pypy/translator/goal/pypy-c
+^pypy/translator/goal/.+\.exe$
+^pypy/translator/goal/target.+-c$
+^pypy/_cache$
+^site-packages/.+\.egg$
+^site-packages/.+\.pth$
+^pypy/doc/statistic/.+\.html$
+^pypy/doc/statistic/.+\.eps$
+^pypy/doc/statistic/.+\.pdf$
+^pypy/translator/cli/src/pypylib\.dll$
+^pypy/translator/cli/src/query\.exe$
+^pypy/translator/cli/src/main\.exe$
+^lib_pypy/ctypes_config_cache/_.+_cache\.py$
+^lib_pypy/ctypes_config_cache/_.+_.+_\.py$
+^pypy/translator/cli/query-descriptions$
+^pypy/doc/discussion/.+\.html$
+^include/.+\.h$
+^include/.+\.inl$
+^pypy/doc/config/.+\.html$
+^pypy/doc/config/style\.css$
+^pypy/doc/jit/.+\.html$
+^pypy/doc/jit/style\.css$
+^pypy/doc/image/lattice1\.png$
+^pypy/doc/image/lattice2\.png$
+^pypy/doc/image/lattice3\.png$
+^pypy/doc/image/stackless_informal\.png$
+^pypy/doc/image/parsing_example.+\.png$


--- a/pypy/interpreter/baseobjspace.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/interpreter/baseobjspace.py	Sun Dec 19 14:45:54 2010 +0100
@@ -555,6 +555,9 @@
 
     def setup_builtin_modules(self):
         "NOT_RPYTHON: only for initializing the space."
+        if self.config.objspace.usemodules.cpyext:
+            from pypy.module.cpyext.state import State
+            self.fromcache(State).build_api(self)
         self.getbuiltinmodule('sys')
         self.getbuiltinmodule('imp')
         self.getbuiltinmodule('__builtin__')


--- a/pypy/module/cpyext/__init__.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/__init__.py	Sun Dec 19 14:45:54 2010 +0100
@@ -12,30 +12,8 @@
     appleveldefs = {
     }
 
-    def setup_after_space_initialization(self):
-        """NOT_RPYTHON"""
-        state = self.space.fromcache(State)
-        if not self.space.config.translating:
-            state.api_lib = str(api.build_bridge(self.space))
-        else:
-            api.setup_library(self.space)
-
     def startup(self, space):
-        state = space.fromcache(State)
-        from pypy.module.cpyext.typeobject import setup_new_method_def
-        from pypy.module.cpyext.pyobject import RefcountState
-        setup_new_method_def(space)
-        if not we_are_translated():
-            space.setattr(space.wrap(self),
-                          space.wrap('api_lib'),
-                          space.wrap(state.api_lib))
-        else:
-            refcountstate = space.fromcache(RefcountState)
-            refcountstate.init_r2w_from_w2r()
-
-        for func in api.INIT_FUNCTIONS:
-            func(space)
-            state.check_and_raise_exception()
+        space.fromcache(State).startup(space)
 
 # import these modules to register api functions by side-effect
 import pypy.module.cpyext.thread
@@ -70,6 +48,7 @@
 import pypy.module.cpyext.funcobject
 import pypy.module.cpyext.classobject
 import pypy.module.cpyext.pypyintf
+import pypy.module.cpyext.memoryobject
 import pypy.module.cpyext.codecs
 
 # now that all rffi_platform.Struct types are registered, configure them


--- a/pypy/module/cpyext/api.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/api.py	Sun Dec 19 14:45:54 2010 +0100
@@ -320,6 +320,11 @@
     'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr',
     'PyCObject_Type', 'init_pycobject',
 
+    'PyCapsule_New', 'PyCapsule_IsValid', 'PyCapsule_GetPointer',
+    'PyCapsule_GetName', 'PyCapsule_GetDestructor', 'PyCapsule_GetContext',
+    'PyCapsule_SetPointer', 'PyCapsule_SetName', 'PyCapsule_SetDestructor',
+    'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', 'init_capsule',
+
     'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
 
     'PyStructSequence_InitType', 'PyStructSequence_New',
@@ -564,9 +569,11 @@
 def setup_init_functions(eci):
     init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void, compilation_info=eci)
     init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void, compilation_info=eci)
+    init_capsule = rffi.llexternal('init_capsule', [], lltype.Void, compilation_info=eci)
     INIT_FUNCTIONS.extend([
         lambda space: init_buffer(),
         lambda space: init_pycobject(),
+        lambda space: init_capsule(),
     ])
 
 def init_function(func):
@@ -657,6 +664,8 @@
     import ctypes
     bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL)
 
+    space.fromcache(State).install_dll(eci)
+
     # populate static data
     for name, (typ, expr) in GLOBALS.iteritems():
         from pypy.module import cpyext
@@ -836,6 +845,25 @@
             structs.append('%s %s = NULL;' % (typ, name))
     struct_source = '\n'.join(structs)
 
+    separate_module_sources = [code, struct_source]
+
+    if sys.platform == 'win32':
+        get_pythonapi_source = '''
+        #include <windows.h>
+        HANDLE pypy_get_pythonapi_handle() {
+            MEMORY_BASIC_INFORMATION  mi;
+            memset(&mi, 0, sizeof(mi));
+
+            if( !VirtualQueryEx(GetCurrentProcess(), &pypy_get_pythonapi_handle,
+                                &mi, sizeof(mi)) )
+                return 0;
+
+            return (HMODULE)mi.AllocationBase;
+        }
+        '''
+        separate_module_sources.append(get_pythonapi_source)
+        export_symbols_eci.append('pypy_get_pythonapi_handle')
+
     eci = ExternalCompilationInfo(
         include_dirs=include_dirs,
         separate_module_files=[source_dir / "varargwrapper.c",
@@ -849,12 +877,14 @@
                                source_dir / "object.c",
                                source_dir / "cobject.c",
                                source_dir / "structseq.c",
+                               source_dir / "capsule.c",
                                ],
-        separate_module_sources = [code, struct_source],
+        separate_module_sources=separate_module_sources,
         export_symbols=export_symbols_eci,
         compile_extra=compile_extra,
         **kwds
         )
+
     return eci
 
 
@@ -873,6 +903,8 @@
 
     eci = build_eci(False, export_symbols, code)
 
+    space.fromcache(State).install_dll(eci)
+
     run_bootstrap_functions(space)
     setup_va_functions(eci)
 


--- a/pypy/module/cpyext/funcobject.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/funcobject.py	Sun Dec 19 14:45:54 2010 +0100
@@ -1,10 +1,12 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
-    PyObjectFields, generic_cpy_call,
+    PyObjectFields, generic_cpy_call, CONST_STRING,
     cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, borrow_from)
+from pypy.interpreter.error import OperationError
 from pypy.interpreter.function import Function, Method
+from pypy.interpreter.pycode import PyCode
 
 PyFunctionObjectStruct = lltype.ForwardReference()
 PyFunctionObject = lltype.Ptr(PyFunctionObjectStruct)
@@ -63,3 +65,22 @@
     assert isinstance(w_method, Method)
     return borrow_from(w_method, w_method.w_class)
 
+ at cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real], PyObject)
+def PyCode_NewEmpty(space, filename, funcname, firstlineno):
+    """Creates a new empty code object with the specified source location."""
+    return space.wrap(PyCode(space,
+                             argcount=0,
+                             nlocals=0,
+                             stacksize=0,
+                             flags=0,
+                             code="",
+                             consts=[],
+                             names=[],
+                             varnames=[],
+                             filename=rffi.charp2str(filename),
+                             name=rffi.charp2str(funcname),
+                             firstlineno=rffi.cast(lltype.Signed, firstlineno),
+                             lnotab="",
+                             freevars=[],
+                             cellvars=[]))
+


--- a/pypy/module/cpyext/import_.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/import_.py	Sun Dec 19 14:45:54 2010 +0100
@@ -39,3 +39,9 @@
 @cpython_api([CONST_STRING], PyObject)
 def PyImport_ImportModule(space, name):
     return PyImport_Import(space, space.wrap(rffi.charp2str(name)))
+
+ at cpython_api([CONST_STRING], PyObject)
+def PyImport_ImportModuleNoBlock(space, name):
+    space.warn('PyImport_ImportModuleNoBlock() is not non-blocking',
+               space.w_RuntimeWarning)
+    return PyImport_Import(space, space.wrap(rffi.charp2str(name)))


--- a/pypy/module/cpyext/include/Python.h	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/include/Python.h	Sun Dec 19 14:45:54 2010 +0100
@@ -112,6 +112,7 @@
 #include "eval.h"
 #include "pymem.h"
 #include "pycobject.h"
+#include "pycapsule.h"
 #include "bufferobject.h"
 #include "sliceobject.h"
 #include "datetime.h"


--- a/pypy/module/cpyext/include/complexobject.h	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/include/complexobject.h	Sun Dec 19 14:45:54 2010 +0100
@@ -1,27 +1,27 @@
-/* Complex object interface */
-
-#ifndef Py_COMPLEXOBJECT_H
-#define Py_COMPLEXOBJECT_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct Py_complex_t {
-    double real;
-    double imag;
-} Py_complex;
-
-/* generated function */
-PyAPI_FUNC(void) _PyComplex_AsCComplex(PyObject *, Py_complex *);
-
-Py_LOCAL_INLINE(Py_complex) PyComplex_AsCComplex(PyObject *obj)
-{
-    Py_complex result;
-    _PyComplex_AsCComplex(obj, &result);
-    return result;
-}
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_COMPLEXOBJECT_H */
+/* Complex object interface */
+
+#ifndef Py_COMPLEXOBJECT_H
+#define Py_COMPLEXOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Py_complex_t {
+    double real;
+    double imag;
+} Py_complex;
+
+/* generated function */
+PyAPI_FUNC(void) _PyComplex_AsCComplex(PyObject *, Py_complex *);
+
+Py_LOCAL_INLINE(Py_complex) PyComplex_AsCComplex(PyObject *obj)
+{
+    Py_complex result;
+    _PyComplex_AsCComplex(obj, &result);
+    return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_COMPLEXOBJECT_H */


--- a/pypy/module/cpyext/include/datetime.h	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/include/datetime.h	Sun Dec 19 14:45:54 2010 +0100
@@ -1,30 +1,30 @@
-#ifndef DATETIME_H
-#define DATETIME_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Define structure for C API. */
-typedef struct {
-    /* type objects */
-    PyTypeObject *DateType;
-    PyTypeObject *DateTimeType;
-    PyTypeObject *TimeType;
-    PyTypeObject *DeltaType;
-} PyDateTime_CAPI;
-
-PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI;
-#define PyDateTime_IMPORT                           \
-    do {                                            \
-        if(PyDateTimeAPI==NULL)                     \
-            PyDateTimeAPI = _PyDateTime_Import();   \
-    } while (0)
-
-typedef struct {
-    PyObject_HEAD
-} PyDateTime_Delta;
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+#ifndef DATETIME_H
+#define DATETIME_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Define structure for C API. */
+typedef struct {
+    /* type objects */
+    PyTypeObject *DateType;
+    PyTypeObject *DateTimeType;
+    PyTypeObject *TimeType;
+    PyTypeObject *DeltaType;
+} PyDateTime_CAPI;
+
+PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI;
+#define PyDateTime_IMPORT                           \
+    do {                                            \
+        if(PyDateTimeAPI==NULL)                     \
+            PyDateTimeAPI = _PyDateTime_Import();   \
+    } while (0)
+
+typedef struct {
+    PyObject_HEAD
+} PyDateTime_Delta;
+
+#ifdef __cplusplus
+}
+#endif
+#endif


--- a/pypy/module/cpyext/include/object.h	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/include/object.h	Sun Dec 19 14:45:54 2010 +0100
@@ -55,11 +55,9 @@
                 }				\
         } while (0)
 
-#if 0  /* This will be added with python 2.6 */
 #define Py_REFCNT(ob)		(((PyObject*)(ob))->ob_refcnt)
 #define Py_TYPE(ob)		(((PyObject*)(ob))->ob_type)
 #define Py_SIZE(ob)		(((PyVarObject*)(ob))->ob_size)
-#endif /* This will be added with python 2.6 */
 
 #define Py_None (&_Py_NoneStruct)
 


--- a/pypy/module/cpyext/include/patchlevel.h	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/include/patchlevel.h	Sun Dec 19 14:45:54 2010 +0100
@@ -21,15 +21,15 @@
 /* Version parsed out into numeric values */
 #define PY_MAJOR_VERSION	2
 #define PY_MINOR_VERSION	5
-#define PY_MICRO_VERSION	5
+#define PY_MICRO_VERSION	2
 #define PY_RELEASE_LEVEL	PY_RELEASE_LEVEL_FINAL
 #define PY_RELEASE_SERIAL	0
 
 /* Version as a string */
-#define PY_VERSION		"2.5.5"
+#define PY_VERSION		"2.5.2"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "1.2.0"
+#define PYPY_VERSION "1.4.0"
 
 /* Subversion Revision number of this file (not of the repository) */
 #define PY_PATCHLEVEL_REVISION  "$Revision: 77872 $"


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/include/pycapsule.h	Sun Dec 19 14:45:54 2010 +0100
@@ -0,0 +1,56 @@
+
+/* Capsule objects let you wrap a C "void *" pointer in a Python
+   object.  They're a way of passing data through the Python interpreter
+   without creating your own custom type.
+
+   Capsules are used for communication between extension modules.
+   They provide a way for an extension module to export a C interface
+   to other extension modules, so that extension modules can use the
+   Python import mechanism to link to one another.
+
+   For more information, please see "c-api/capsule.html" in the
+   documentation.
+*/
+
+#ifndef Py_CAPSULE_H
+#define Py_CAPSULE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_DATA(PyTypeObject) PyCapsule_Type;
+
+typedef void (*PyCapsule_Destructor)(PyObject *);
+
+#define PyCapsule_CheckExact(op) (Py_TYPE(op) == &PyCapsule_Type)
+
+
+PyAPI_FUNC(PyObject *) PyCapsule_New(
+    void *pointer,
+    const char *name,
+    PyCapsule_Destructor destructor);
+
+PyAPI_FUNC(void *) PyCapsule_GetPointer(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(PyCapsule_Destructor) PyCapsule_GetDestructor(PyObject *capsule);
+
+PyAPI_FUNC(const char *) PyCapsule_GetName(PyObject *capsule);
+
+PyAPI_FUNC(void *) PyCapsule_GetContext(PyObject *capsule);
+
+PyAPI_FUNC(int) PyCapsule_IsValid(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(int) PyCapsule_SetPointer(PyObject *capsule, void *pointer);
+
+PyAPI_FUNC(int) PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor);
+
+PyAPI_FUNC(int) PyCapsule_SetName(PyObject *capsule, const char *name);
+
+PyAPI_FUNC(int) PyCapsule_SetContext(PyObject *capsule, void *context);
+
+PyAPI_FUNC(void *) PyCapsule_Import(const char *name, int no_block);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CAPSULE_H */


--- a/pypy/module/cpyext/include/pythonrun.h	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/include/pythonrun.h	Sun Dec 19 14:45:54 2010 +0100
@@ -8,6 +8,9 @@
 
   void Py_FatalError(const char *msg);
 
+/* the -3 option will probably not be implemented */
+#define Py_Py3kWarningFlag 0
+
 #ifdef __cplusplus
 }
 #endif


--- a/pypy/module/cpyext/intobject.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/intobject.py	Sun Dec 19 14:45:54 2010 +0100
@@ -95,4 +95,3 @@
     if pend:
         pend[0] = rffi.ptradd(str, len(s))
     return space.call_function(space.w_int, w_str, w_base)
-


--- a/pypy/module/cpyext/longobject.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/longobject.py	Sun Dec 19 14:45:54 2010 +0100
@@ -1,6 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.module.cpyext.api import (cpython_api, PyObject, build_type_checkers,
-                                    CONST_STRING, ADDR)
+                                    CONST_STRING, ADDR, CANNOT_FAIL)
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.interpreter.error import OperationError
 from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask
@@ -168,3 +168,13 @@
     For values outside 0..LONG_MAX, both signed and unsigned integers are accepted."""
     return rffi.cast(rffi.VOIDP_real, space.uint_w(w_long))
 
+ at cpython_api([PyObject], rffi.SIZE_T, error=-1)
+def _PyLong_NumBits(space, w_long):
+    return space.uint_w(space.call_method(w_long, "bit_length"))
+
+ at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def _PyLong_Sign(space, w_long):
+    assert isinstance(w_long, W_LongObject)
+    return w_long.num.sign
+
+


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/memoryobject.py	Sun Dec 19 14:45:54 2010 +0100
@@ -0,0 +1,6 @@
+from pypy.module.cpyext.api import cpython_api
+from pypy.module.cpyext.pyobject import PyObject
+
+ at cpython_api([PyObject], PyObject)
+def PyMemoryView_FromObject(space, w_obj):
+    return space.call_method(space.builtin, "memoryview", w_obj)


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/src/capsule.c	Sun Dec 19 14:45:54 2010 +0100
@@ -0,0 +1,328 @@
+/* Wrap void * pointers to be passed between C modules */
+
+#include "Python.h"
+
+/* Internal structure of PyCapsule */
+typedef struct {
+    PyObject_HEAD
+    void *pointer;
+    const char *name;
+    void *context;
+    PyCapsule_Destructor destructor;
+} PyCapsule;
+
+
+
+static int
+_is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
+{
+    if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
+        PyErr_SetString(PyExc_ValueError, invalid_capsule);
+        return 0;
+    }
+    return 1;
+}
+
+#define is_legal_capsule(capsule, name) \
+    (_is_legal_capsule(capsule, \
+     name " called with invalid PyCapsule object"))
+
+
+static int
+name_matches(const char *name1, const char *name2) {
+    /* if either is NULL, */
+    if (!name1 || !name2) {
+        /* they're only the same if they're both NULL. */
+        return name1 == name2;
+    }
+    return !strcmp(name1, name2);
+}
+
+
+
+PyObject *
+PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
+{
+    PyCapsule *capsule;
+
+    if (!pointer) {
+        PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
+        return NULL;
+    }
+
+    capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
+    if (capsule == NULL) {
+        return NULL;
+    }
+
+    capsule->pointer = pointer;
+    capsule->name = name;
+    capsule->context = NULL;
+    capsule->destructor = destructor;
+
+    return (PyObject *)capsule;
+}
+
+
+int
+PyCapsule_IsValid(PyObject *o, const char *name)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    return (capsule != NULL &&
+            PyCapsule_CheckExact(capsule) &&
+            capsule->pointer != NULL &&
+            name_matches(capsule->name, name));
+}
+
+
+void *
+PyCapsule_GetPointer(PyObject *o, const char *name)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
+        return NULL;
+    }
+
+    if (!name_matches(name, capsule->name)) {
+        PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");
+        return NULL;
+    }
+
+    return capsule->pointer;
+}
+
+
+const char *
+PyCapsule_GetName(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {
+        return NULL;
+    }
+    return capsule->name;
+}
+
+
+PyCapsule_Destructor
+PyCapsule_GetDestructor(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {
+        return NULL;
+    }
+    return capsule->destructor;
+}
+
+
+void *
+PyCapsule_GetContext(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {
+        return NULL;
+    }
+    return capsule->context;
+}
+
+
+int
+PyCapsule_SetPointer(PyObject *o, void *pointer)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!pointer) {
+        PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");
+        return -1;
+    }
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {
+        return -1;
+    }
+
+    capsule->pointer = pointer;
+    return 0;
+}
+
+
+int
+PyCapsule_SetName(PyObject *o, const char *name)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {
+        return -1;
+    }
+
+    capsule->name = name;
+    return 0;
+}
+
+
+int
+PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
+        return -1;
+    }
+
+    capsule->destructor = destructor;
+    return 0;
+}
+
+
+int
+PyCapsule_SetContext(PyObject *o, void *context)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+
+    if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {
+        return -1;
+    }
+
+    capsule->context = context;
+    return 0;
+}
+
+
+void *
+PyCapsule_Import(const char *name, int no_block)
+{
+    PyObject *object = NULL;
+    void *return_value = NULL;
+    char *trace;
+    size_t name_length = (strlen(name) + 1) * sizeof(char);
+    char *name_dup = (char *)PyMem_MALLOC(name_length);
+
+    if (!name_dup) {
+        return NULL;
+    }
+
+    memcpy(name_dup, name, name_length);
+
+    trace = name_dup;
+    while (trace) {
+        char *dot = strchr(trace, '.');
+        if (dot) {
+            *dot++ = '\0';
+        }
+
+        if (object == NULL) {
+            if (no_block) {
+                object = PyImport_ImportModuleNoBlock(trace);
+            } else {
+                object = PyImport_ImportModule(trace);
+                if (!object) {
+                    PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
+                }
+            }
+        } else {
+            PyObject *object2 = PyObject_GetAttrString(object, trace);
+            Py_DECREF(object);
+            object = object2;
+        }
+        if (!object) {
+            goto EXIT;
+        }
+
+        trace = dot;
+    }
+
+    /* compare attribute name to module.name by hand */
+    if (PyCapsule_IsValid(object, name)) {
+        PyCapsule *capsule = (PyCapsule *)object;
+        return_value = capsule->pointer;
+    } else {
+        PyErr_Format(PyExc_AttributeError,
+            "PyCapsule_Import \"%s\" is not valid",
+            name);
+    }
+
+EXIT:
+    Py_XDECREF(object);
+    if (name_dup) {
+        PyMem_FREE(name_dup);
+    }
+    return return_value;
+}
+
+
+static void
+capsule_dealloc(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+    if (capsule->destructor) {
+        capsule->destructor(o);
+    }
+    PyObject_DEL(o);
+}
+
+
+static PyObject *
+capsule_repr(PyObject *o)
+{
+    PyCapsule *capsule = (PyCapsule *)o;
+    const char *name;
+    const char *quote;
+
+    if (capsule->name) {
+        quote = "\"";
+        name = capsule->name;
+    } else {
+        quote = "";
+        name = "NULL";
+    }
+
+    return PyString_FromFormat("<capsule object %s%s%s at %p>",
+        quote, name, quote, capsule);
+}
+
+
+
+PyDoc_STRVAR(PyCapsule_Type__doc__,
+"Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
+object.  They're a way of passing data through the Python interpreter\n\
+without creating your own custom type.\n\
+\n\
+Capsules are used for communication between extension modules.\n\
+They provide a way for an extension module to export a C interface\n\
+to other extension modules, so that extension modules can use the\n\
+Python import mechanism to link to one another.\n\
+");
+
+PyTypeObject PyCapsule_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    "PyCapsule",		/*tp_name*/
+    sizeof(PyCapsule),		/*tp_basicsize*/
+    0,				/*tp_itemsize*/
+    /* methods */
+    capsule_dealloc, /*tp_dealloc*/
+    0,				/*tp_print*/
+    0,				/*tp_getattr*/
+    0,				/*tp_setattr*/
+    0,				/*tp_reserved*/
+    capsule_repr, /*tp_repr*/
+    0,				/*tp_as_number*/
+    0,				/*tp_as_sequence*/
+    0,				/*tp_as_mapping*/
+    0,				/*tp_hash*/
+    0,				/*tp_call*/
+    0,				/*tp_str*/
+    0,				/*tp_getattro*/
+    0,				/*tp_setattro*/
+    0,				/*tp_as_buffer*/
+    0,				/*tp_flags*/
+    PyCapsule_Type__doc__	/*tp_doc*/
+};
+
+void init_capsule()
+{
+    PyType_Ready(&PyCapsule_Type);
+}
+


--- a/pypy/module/cpyext/src/structseq.c	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/src/structseq.c	Sun Dec 19 14:45:54 2010 +0100
@@ -5,13 +5,6 @@
 #include "structmember.h"
 #include "structseq.h"
 
-#ifdef Py_TYPE
-#error "Please remove these definitions"
-#else
-#define Py_TYPE(ob)		(((PyObject*)(ob))->ob_type)
-#define Py_SIZE(ob)		(((PyVarObject*)(ob))->ob_size)
-#endif
-
 static char visible_length_key[] = "n_sequence_fields";
 static char real_length_key[] = "n_fields";
 static char unnamed_fields_key[] = "n_unnamed_fields";


--- a/pypy/module/cpyext/state.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/state.py	Sun Dec 19 14:45:54 2010 +0100
@@ -2,7 +2,8 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import lltype
-
+from pypy.rlib.rdynload import DLLHANDLE
+import sys
 
 class State:
     def __init__(self, space):
@@ -43,6 +44,46 @@
             raise OperationError(self.space.w_SystemError, self.space.wrap(
                 "Function returned an error result without setting an exception"))
 
+    def build_api(self, space):
+        """NOT_RPYTHON
+        This function is called when at object space creation,
+        and drives the compilation of the cpyext library
+        """
+        from pypy.module.cpyext import api
+        state = self.space.fromcache(State)
+        if not self.space.config.translating:
+            state.api_lib = str(api.build_bridge(self.space))
+        else:
+            api.setup_library(self.space)
+
+    def install_dll(self, eci):
+        """NOT_RPYTHON
+        Called when the dll has been compiled"""
+        if sys.platform == 'win32':
+            self.get_pythonapi_handle = rffi.llexternal(
+                'pypy_get_pythonapi_handle', [], DLLHANDLE,
+                compilation_info=eci)
+
+    def startup(self, space):
+        "This function is called when the program really starts"
+
+        from pypy.module.cpyext.typeobject import setup_new_method_def
+        from pypy.module.cpyext.pyobject import RefcountState
+        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:
+            refcountstate = space.fromcache(RefcountState)
+            refcountstate.init_r2w_from_w2r()
+
+        for func in INIT_FUNCTIONS:
+            func(space)
+            self.check_and_raise_exception()
+
     def get_programname(self):
         if not self.programname:
             space = self.space


--- a/pypy/module/cpyext/stubs.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/stubs.py	Sun Dec 19 14:45:54 2010 +0100
@@ -328,18 +328,6 @@
     used as the positional and keyword parameters to the object's constructor."""
     raise NotImplementedError
 
- at cpython_api([PyObject], rffi.VOIDP_real, error=lltype.nullptr(rffi.VOIDP.TO))
-def PyCObject_GetDesc(space, self):
-    """Return the description void * that the PyCObject self was
-    created with."""
-    raise NotImplementedError
-
- at cpython_api([PyObject, rffi.VOIDP_real], rffi.INT_real, error=0)
-def PyCObject_SetVoidPtr(space, self, cobj):
-    """Set the void pointer inside self to cobj. The PyCObject must not
-    have an associated destructor. Return true on success, false on failure."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyCode_Check(space, co):
     """Return true if co is a code object"""


--- a/pypy/module/cpyext/test/conftest.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/test/conftest.py	Sun Dec 19 14:45:54 2010 +0100
@@ -9,7 +9,7 @@
     return False
 
 def pytest_funcarg__space(request):
-    return gettestobjspace(usemodules=['cpyext', 'thread'])
+    return gettestobjspace(usemodules=['cpyext', 'thread', '_rawffi'])
 
 def pytest_funcarg__api(request):
     return request.cls.api


--- a/pypy/module/cpyext/test/test_api.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/test/test_api.py	Sun Dec 19 14:45:54 2010 +0100
@@ -19,7 +19,7 @@
 
 class BaseApiTest(LeakCheckingTest):
     def setup_class(cls):
-        cls.space = space = gettestobjspace(usemodules=['cpyext', 'thread'])
+        cls.space = space = gettestobjspace(usemodules=['cpyext', 'thread', '_rawffi'])
 
         # warm up reference counts:
         # - the posix module allocates a HCRYPTPROV on Windows


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/test/test_capsule.py	Sun Dec 19 14:45:54 2010 +0100
@@ -0,0 +1,29 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+class AppTestCapsule(AppTestCpythonExtensionBase):
+    def test_capsule_import(self):
+        module = self.import_extension('foo', [
+            ("set_ptr", "METH_O",
+             """
+                 PyObject *capsule, *module;
+                 void *ptr = PyLong_AsVoidPtr(args);
+                 if (PyErr_Occurred()) return NULL;
+                 capsule = PyCapsule_New(ptr, "foo._ptr", NULL);
+                 if (PyErr_Occurred()) return NULL;
+                 module = PyImport_ImportModule("foo");
+                 PyModule_AddObject(module, "_ptr", capsule);
+                 Py_DECREF(module);
+                 if (PyErr_Occurred()) return NULL;
+                 Py_RETURN_NONE;
+             """),
+            ("get_ptr", "METH_NOARGS",
+             """
+                 void *ptr = PyCapsule_Import("foo._ptr", 0);
+                 if (PyErr_Occurred()) return NULL;
+                 return PyLong_FromVoidPtr(ptr);
+             """)])
+        module.set_ptr(1234)
+        assert 'capsule object "foo._ptr" at ' in str(module._ptr)
+        import gc; gc.collect()
+        assert module.get_ptr() == 1234
+        del module._ptr


--- a/pypy/module/cpyext/test/test_cpyext.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/test/test_cpyext.py	Sun Dec 19 14:45:54 2010 +0100
@@ -35,7 +35,7 @@
 
 class AppTestApi:
     def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=['cpyext', 'thread'])
+        cls.space = gettestobjspace(usemodules=['cpyext', 'thread', '_rawffi'])
         from pypy.rlib.libffi import get_libc_name
         cls.w_libc = cls.space.wrap(get_libc_name())
 
@@ -44,6 +44,17 @@
         raises(ImportError, cpyext.load_module, "missing.file", "foo")
         raises(ImportError, cpyext.load_module, self.libc, "invalid.function")
 
+    def test_dllhandle(self):
+        import sys
+        if sys.version_info < (2, 6):
+            skip("Python >= 2.6 only")
+        assert sys.dllhandle
+        assert sys.dllhandle.getaddressindll('PyPyErr_NewException')
+        import ctypes # slow
+        PyUnicode_GetDefaultEncoding = ctypes.pythonapi.PyPyUnicode_GetDefaultEncoding
+        PyUnicode_GetDefaultEncoding.restype = ctypes.c_char_p
+        assert PyUnicode_GetDefaultEncoding() == 'ascii'
+
 def compile_module(space, modname, **kwds):
     """
     Build an extension module and return the filename of the resulting native
@@ -147,7 +158,7 @@
 
 class AppTestCpythonExtensionBase(LeakCheckingTest):
     def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=['cpyext', 'thread'])
+        cls.space = gettestobjspace(usemodules=['cpyext', 'thread', '_rawffi'])
         cls.space.getbuiltinmodule("cpyext")
         from pypy.module.imp.importing import importhook
         importhook(cls.space, "os") # warm up reference counts


--- a/pypy/module/cpyext/test/test_funcobject.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/test/test_funcobject.py	Sun Dec 19 14:45:54 2010 +0100
@@ -35,3 +35,12 @@
 
         w_method2 = api.PyMethod_New(w_function, w_self, w_class)
         assert space.eq_w(w_method, w_method2)
+
+    def test_newcode(self, space, api):
+        filename = rffi.str2charp('filename')
+        funcname = rffi.str2charp('funcname')
+        w_code = api.PyCode_NewEmpty(filename, funcname, 3)
+        assert w_code.co_filename == 'filename'
+        assert w_code.co_firstlineno == 3
+        rffi.free_charp(filename)
+        rffi.free_charp(funcname)


--- a/pypy/module/cpyext/test/test_longobject.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/module/cpyext/test/test_longobject.py	Sun Dec 19 14:45:54 2010 +0100
@@ -1,4 +1,4 @@
-import sys
+import sys, py
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.objspace.std.intobject import W_IntObject
 from pypy.objspace.std.longobject import W_LongObject
@@ -96,6 +96,23 @@
         assert space.unwrap(w_l) == 0L
         assert api.PyLong_AsVoidPtr(w_l) == lltype.nullptr(rffi.VOIDP_real.TO)
 
+    def test_sign_and_bits(self, space, api):
+        if space.is_true(space.lt(space.sys.get('version_info'),
+                                  space.wrap((2, 7)))):
+            py.test.skip("unsupported before Python 2.7")
+
+        assert api._PyLong_Sign(space.wrap(0L)) == 0
+        assert api._PyLong_Sign(space.wrap(2L)) == 1
+        assert api._PyLong_Sign(space.wrap(-2L)) == -1
+
+        assert api._PyLong_NumBits(space.wrap(0)) == 0
+        assert api._PyLong_NumBits(space.wrap(1)) == 1
+        assert api._PyLong_NumBits(space.wrap(-1)) == 1
+        assert api._PyLong_NumBits(space.wrap(2)) == 2
+        assert api._PyLong_NumBits(space.wrap(-2)) == 2
+        assert api._PyLong_NumBits(space.wrap(3)) == 2
+        assert api._PyLong_NumBits(space.wrap(-3)) == 2
+
 class AppTestLongObject(AppTestCpythonExtensionBase):
     def test_fromunsignedlong(self):
         module = self.import_extension('foo', [


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/test/test_memoryobject.py	Sun Dec 19 14:45:54 2010 +0100
@@ -0,0 +1,13 @@
+import py
+from pypy.module.cpyext.test.test_api import BaseApiTest
+
+class TestMemoryViewObject(BaseApiTest):
+    def test_fromobject(self, space, api):
+        if space.is_true(space.lt(space.sys.get('version_info'),
+                                  space.wrap((2, 7)))):
+            py.test.skip("unsupported before Python 2.7")
+
+        w_hello = space.wrap("hello")
+        w_view = api.PyMemoryView_FromObject(w_hello)
+        w_bytes = space.call_method(w_view, "tobytes")
+        assert space.unwrap(w_bytes) == "hello"


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/test/test_version.py	Sun Dec 19 14:45:54 2010 +0100
@@ -0,0 +1,17 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+
+class AppTestVersion(AppTestCpythonExtensionBase):
+
+    def test_versions(self):
+        import sys
+        init = """
+        if (Py_IsInitialized()) {
+            PyObject *m = Py_InitModule("foo", NULL);
+            PyModule_AddStringConstant(m, "py_version", PY_VERSION);
+            PyModule_AddStringConstant(m, "pypy_version", PYPY_VERSION);
+        }
+        """
+        module = self.import_module(name='foo', init=init)
+        assert module.py_version == sys.version[:5]
+        assert module.pypy_version == '%d.%d.%d' % sys.pypy_version_info[:3]


--- a/pypy/rlib/rdynload.py	Sun Dec 19 13:09:34 2010 +0100
+++ b/pypy/rlib/rdynload.py	Sun Dec 19 14:45:54 2010 +0100
@@ -67,6 +67,8 @@
     c_dlerror = external('dlerror', [], rffi.CCHARP)
     c_dlsym = external('dlsym', [rffi.VOIDP, rffi.CCHARP], rffi.VOIDP)
 
+    DLLHANDLE = rffi.VOIDP
+
     RTLD_LOCAL = cConfig.RTLD_LOCAL
     RTLD_GLOBAL = cConfig.RTLD_GLOBAL
     RTLD_NOW = cConfig.RTLD_NOW
@@ -110,6 +112,8 @@
         raise KeyError(index)
 
 if _WIN32:
+    DLLHANDLE = rwin32.HMODULE
+
     def dlopen(name):
         res = rwin32.LoadLibrary(name)
         if not res:

Repository URL: https://bitbucket.org/pypy/pypy/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.



More information about the Pypy-commit mailing list