[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