[pypy-svn] commit/pypy: 4 new changesets

Bitbucket commits-noreply at bitbucket.org
Sun Dec 19 11:52:13 CET 2010


4 new changesets in pypy:

http://bitbucket.org/pypy/pypy/changeset/fec479970f6d/
changeset:   r40120:fec479970f6d
branch:      cpyext-2.5-backport
user:        arigo
date:        2010-12-18 16:03:11
summary:     Add a test for the version numbers in patchlevel.h.
affected #:  2 files (637 bytes)

--- a/pypy/module/cpyext/include/patchlevel.h	Sat Dec 18 13:29:01 2010 +0100
+++ b/pypy/module/cpyext/include/patchlevel.h	Sat Dec 18 16:03:11 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/test/test_version.py	Sat Dec 18 16:03:11 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]


http://bitbucket.org/pypy/pypy/changeset/672bc9204bff/
changeset:   r40121:672bc9204bff
branch:      fast-forward
user:        arigo
date:        2010-12-18 12:47:49
summary:     Remove this workaround, which should not be needed any more.
affected #:  1 file (782 bytes)

--- a/pypy/module/cpyext/funcobject.py	Fri Dec 17 19:34:01 2010 +0100
+++ b/pypy/module/cpyext/funcobject.py	Sat Dec 18 12:47:49 2010 +0100
@@ -65,26 +65,6 @@
     assert isinstance(w_method, Method)
     return borrow_from(w_method, w_method.w_class)
 
-# XXX Something that annotates as a list of (W_Root or None)
-# XXX looks like a bug in make_sure_not_modified() used by PyCode.___init__
-# XXX which also depends on the annotation order
-def consts_w():
-    return []
-
-from pypy.rpython import extregistry
-class For_some_const(extregistry.ExtRegistryEntry):
-    _about_ = consts_w
-
-    def compute_result_annotation(self):
-        from pypy.annotation import model as annmodel
-        from pypy.interpreter.baseobjspace import W_Root
-        clsdef = self.bookkeeper.getuniqueclassdef(W_Root)
-        s_value = annmodel.SomeInstance(clsdef, can_be_None=True)
-        return self.bookkeeper.newlist(s_value)
-
-    def specialize_call(self, hop):
-        return hop.rtyper.type_system.rlist.newlist(hop.llops, hop.r_result, [])
-
 @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."""
@@ -94,7 +74,7 @@
                              stacksize=0,
                              flags=0,
                              code="",
-                             consts=consts_w(),
+                             consts=[],
                              names=[],
                              varnames=[],
                              filename=rffi.charp2str(filename),


http://bitbucket.org/pypy/pypy/changeset/8c2427fa1a01/
changeset:   r40122:8c2427fa1a01
branch:      fast-forward
user:        arigo
date:        2010-12-18 13:02:05
summary:     Revert the limitation of tuples-only, now that PyPy_Borrow() is used.
affected #:  1 file (185 bytes)

--- a/pypy/module/cpyext/src/getargs.c	Sat Dec 18 12:47:49 2010 +0100
+++ b/pypy/module/cpyext/src/getargs.c	Sat Dec 18 13:02:05 2010 +0100
@@ -445,23 +445,20 @@
 	for (i = 0; i < n; i++) {
 		char *msg;
 		PyObject *item;
-		/* CPython uses PySequence_GetItem() and Py_XDECREF() here,
-		   exposing a crash (see http://bugs.python.org/issue6083).
-		   It always crashes with PyPy, so we apply the fix being
-		   discussed: we only allow a tuple. */
-		item = PyTuple_GetItem(arg, i);
+        item = PySequence_GetItem(arg, i);
 		if (item == NULL) {
 			PyErr_Clear();
 			levels[0] = i+1;
 			levels[1] = 0;
-			strncpy(msgbuf, "is not retrievable (subargument "
-				        "must be a real tuple with PyPy)",
+			strncpy(msgbuf, "is not retrievable",
 				        bufsize);
 			return msgbuf;
 		}
                 PyPy_Borrow(arg, item);
 		msg = convertitem(item, &format, p_va, flags, levels+1, 
 				  msgbuf, bufsize, freelist);
+        /* PySequence_GetItem calls tp->sq_item, which INCREFs */
+        Py_XDECREF(item);
 		if (msg != NULL) {
 			levels[0] = i+1;
 			return msg;


http://bitbucket.org/pypy/pypy/changeset/c11f111415ab/
changeset:   r40119:c11f111415ab
branch:      cpyext-2.5-backport
user:        arigo
date:        2010-12-18 13:29:01
summary:     Backporting the changes done to cpyext on fast-forward back to the trunk.
affected #:  51 files (43.7 KB)

--- a/pypy/interpreter/baseobjspace.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/interpreter/baseobjspace.py	Sat Dec 18 13:29:01 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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/__init__.py	Sat Dec 18 13:29:01 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,8 @@
 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
 api.configure_types()


--- a/pypy/module/cpyext/api.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/api.py	Sat Dec 18 13:29:01 2010 +0100
@@ -193,7 +193,7 @@
       the API headers.
     """
     if error is _NOT_SPECIFIED:
-        if restype is PyObject:
+        if isinstance(restype, lltype.Ptr):
             error = lltype.nullptr(restype.TO)
         elif restype is lltype.Void:
             error = CANNOT_FAIL
@@ -308,7 +308,7 @@
     'PyModule_AddObject', 'PyModule_AddIntConstant', 'PyModule_AddStringConstant',
     'Py_BuildValue', 'Py_VaBuildValue', 'PyTuple_Pack',
 
-    'PyErr_Format', 'PyErr_NewException',
+    'PyErr_Format', 'PyErr_NewException', 'PyErr_NewExceptionWithDoc',
 
     'PyEval_CallFunction', 'PyEval_CallMethod', 'PyObject_CallFunction',
     'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
@@ -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
@@ -746,6 +755,7 @@
         ("SIZEOF_LONG_LONG", rffi.LONGLONG),
         ("SIZEOF_VOID_P", rffi.VOIDP),
         ("SIZEOF_SIZE_T", rffi.SIZE_T),
+        ("SIZEOF_TIME_T", rffi.TIME_T),
         ("SIZEOF_LONG", rffi.LONG),
         ("SIZEOF_SHORT", rffi.SHORT),
         ("SIZEOF_INT", rffi.INT)
@@ -835,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",
@@ -848,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
 
 
@@ -872,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/cdatetime.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/cdatetime.py	Sat Dec 18 13:29:01 2010 +0100
@@ -18,8 +18,7 @@
      ('DeltaType', PyTypeObjectPtr),
      ))
 
- at cpython_api([], lltype.Ptr(PyDateTime_CAPI),
-             error=lltype.nullptr(PyDateTime_CAPI))
+ at cpython_api([], lltype.Ptr(PyDateTime_CAPI))
 def _PyDateTime_Import(space):
     datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
                                 track_allocation=False)


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/codecs.py	Sat Dec 18 13:29:01 2010 +0100
@@ -0,0 +1,22 @@
+from pypy.rpython.lltypesystem import rffi
+from pypy.module.cpyext.api import cpython_api, PyObject, CONST_STRING
+from pypy.module._codecs import interp_codecs
+
+ at cpython_api([CONST_STRING, CONST_STRING], PyObject)
+def PyCodec_IncrementalEncoder(space, encoding, errors):
+    w_codec = interp_codecs.lookup_codec(space, rffi.charp2str(encoding))
+    if errors:
+        w_errors = space.wrap(rffi.charp2str(errors))
+        return space.call_method(w_codec, "incrementalencoder", w_errors)
+    else:
+        return space.call_method(w_codec, "incrementalencoder")
+
+ at cpython_api([CONST_STRING, CONST_STRING], PyObject)
+def PyCodec_IncrementalDecoder(space, encoding, errors):
+    w_codec = interp_codecs.lookup_codec(space, rffi.charp2str(encoding))
+    if errors:
+        w_errors = space.wrap(rffi.charp2str(errors))
+        return space.call_method(w_codec, "incrementaldecoder", w_errors)
+    else:
+        return space.call_method(w_codec, "incrementaldecoder")
+


--- a/pypy/module/cpyext/complexobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/complexobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -36,7 +36,7 @@
 
 # lltype does not handle functions returning a structure.  This implements a
 # helper function, which takes as argument a reference to the return value.
- at cpython_api([PyObject, Py_complex_ptr], lltype.Void, error=None)
+ at cpython_api([PyObject, Py_complex_ptr], lltype.Void)
 def _PyComplex_AsCComplex(space, w_obj, result):
     """Return the Py_complex value of the complex number op.
 


--- a/pypy/module/cpyext/dictobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/dictobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -67,6 +67,15 @@
     len(p) on a dictionary."""
     return space.int_w(space.len(w_obj))
 
+ at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
+def PyDict_Contains(space, w_obj, w_value):
+    """Determine if dictionary p contains key.  If an item in p is matches
+    key, return 1, otherwise return 0.  On error, return -1.
+    This is equivalent to the Python expression key in p.
+    """
+    w_res = space.contains(w_obj, w_value)
+    return space.int_w(w_res)
+
 @cpython_api([PyObject], lltype.Void)
 def PyDict_Clear(space, w_obj):
     """Empty an existing dictionary of all key-value pairs."""


--- a/pypy/module/cpyext/floatobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/floatobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -1,6 +1,6 @@
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import (CANNOT_FAIL, cpython_api, PyObject,
-                                    build_type_checkers)
+from pypy.module.cpyext.api import (
+    CANNOT_FAIL, cpython_api, PyObject, build_type_checkers, CONST_STRING)
 from pypy.interpreter.error import OperationError
 
 PyFloat_Check, PyFloat_CheckExact = build_type_checkers("Float")
@@ -24,4 +24,12 @@
     """
     Returns the o converted to a float object on success, or NULL on failure.
     This is the equivalent of the Python expression float(o)."""
-    return space.float(w_obj)
+    return space.call_function(space.w_float, w_obj)
+
+ at cpython_api([PyObject, rffi.CCHARPP], PyObject)
+def PyFloat_FromString(space, w_obj, _):
+    """Create a PyFloatObject object based on the string value in str, or
+    NULL on failure.  The pend argument is ignored.  It remains only for
+    backward compatibility."""
+    return space.call_function(space.w_float, w_obj)
+


--- a/pypy/module/cpyext/funcobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/funcobject.py	Sat Dec 18 13:29:01 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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/import_.py	Sat Dec 18 13:29:01 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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/Python.h	Sat Dec 18 13:29:01 2010 +0100
@@ -34,7 +34,23 @@
 # endif
 # define Py_LOCAL_INLINE(type) static __inline type __fastcall
 #endif
-#define DL_IMPORT(RTYPE) PyAPI_FUNC(RTYPE)
+
+/* Deprecated DL_IMPORT and DL_EXPORT macros */
+#ifdef _WIN32
+# if defined(Py_BUILD_CORE)
+#  define DL_IMPORT(RTYPE) __declspec(dllexport) RTYPE
+#  define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
+# else
+#  define DL_IMPORT(RTYPE) __declspec(dllimport) RTYPE
+#  define DL_EXPORT(RTYPE) __declspec(dllexport) RTYPE
+# endif
+#endif
+#ifndef DL_EXPORT
+#       define DL_EXPORT(RTYPE) RTYPE
+#endif
+#ifndef DL_IMPORT
+#       define DL_IMPORT(RTYPE) RTYPE
+#endif
 
 #include <stdlib.h>
 
@@ -57,10 +73,6 @@
 #define Py_CHARMASK(c)		((unsigned char)((c) & 0xff))
 #endif
 
-#ifndef DL_EXPORT	/* declarations for DLL import/export */
-#define DL_EXPORT(RTYPE) RTYPE
-#endif
-
 #define statichere static
 
 #define Py_MEMCPY memcpy
@@ -68,6 +80,7 @@
 #include <pypy_macros.h>
 
 #include "patchlevel.h"
+#include "pyconfig.h"
 
 #include "object.h"
 #include "pyport.h"
@@ -80,8 +93,6 @@
 #include <locale.h>
 #include <ctype.h>
 
-#include "pyconfig.h"
-
 #include "boolobject.h"
 #include "floatobject.h"
 #include "complexobject.h"
@@ -101,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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/complexobject.h	Sat Dec 18 13:29:01 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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/datetime.h	Sat Dec 18 13:29:01 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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/object.h	Sat Dec 18 13:29:01 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)
 
@@ -461,6 +459,11 @@
 #define PyObject_GC_New(type, typeobj) \
                 ( (type *) _PyObject_GC_New(typeobj) )
 
+/* A dummy PyGC_Head, just to please some tests. Don't use it! */
+typedef union _gc_head {
+    char dummy;
+} PyGC_Head;
+
 /* Utility macro to help write tp_traverse functions.
  * To use this macro, the tp_traverse function must name its arguments
  * "visit" and "arg".  This is intended to keep tp_traverse functions


--- a/pypy/module/cpyext/include/pyconfig.h	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/pyconfig.h	Sat Dec 18 13:29:01 2010 +0100
@@ -10,11 +10,11 @@
 #define HAVE_LONG_LONG 1
 #define HAVE_STDARG_PROTOTYPES 1
 #define PY_FORMAT_LONG_LONG "ll"
-#define PY_LONG_LONG long long
 #define PY_FORMAT_SIZE_T "z"
 #define WITH_DOC_STRINGS
 #define HAVE_UNICODE
 #define WITHOUT_COMPLEX
+#define HAVE_WCHAR_H 1
 
 /* PyPy supposes Py_UNICODE == wchar_t */
 #define HAVE_USABLE_WCHAR_T 1


--- a/pypy/module/cpyext/include/pyerrors.h	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/pyerrors.h	Sat Dec 18 13:29:01 2010 +0100
@@ -7,7 +7,12 @@
 extern "C" {
 #endif
 
+#define PyExceptionClass_Check(x)                                       \
+    (PyClass_Check((x)) || (PyType_Check((x)) &&                        \
+      PyObject_IsSubclass((x), PyExc_BaseException)))
+
 PyObject *PyErr_NewException(char *name, PyObject *base, PyObject *dict);
+PyObject *PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict);
 PyObject *PyErr_Format(PyObject *exception, const char *format, ...);
 
 #ifdef __cplusplus


--- a/pypy/module/cpyext/include/pyport.h	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/pyport.h	Sat Dec 18 13:29:01 2010 +0100
@@ -5,6 +5,29 @@
 #include <stdint.h>
 #endif
 
+/* typedefs for some C9X-defined synonyms for integral types. */
+#ifdef HAVE_LONG_LONG
+#ifndef PY_LONG_LONG
+#define PY_LONG_LONG long long
+#if defined(LLONG_MAX)
+/* If LLONG_MAX is defined in limits.h, use that. */
+#define PY_LLONG_MIN LLONG_MIN
+#define PY_LLONG_MAX LLONG_MAX
+#define PY_ULLONG_MAX ULLONG_MAX
+#elif defined(__LONG_LONG_MAX__)
+/* Otherwise, if GCC has a builtin define, use that. */
+#define PY_LLONG_MAX __LONG_LONG_MAX__
+#define PY_LLONG_MIN (-PY_LLONG_MAX-1)
+#define PY_ULLONG_MAX (__LONG_LONG_MAX__*2ULL + 1ULL)
+#else
+/* Otherwise, rely on two's complement. */
+#define PY_ULLONG_MAX (~0ULL)
+#define PY_LLONG_MAX  ((long long)(PY_ULLONG_MAX>>1))
+#define PY_LLONG_MIN (-PY_LLONG_MAX-1)
+#endif /* LLONG_MAX */
+#endif
+#endif /* HAVE_LONG_LONG */
+
 /* Largest possible value of size_t.
    SIZE_MAX is part of C99, so it might be defined on some
    platforms. If it is not defined, (size_t)-1 is a portable


--- a/pypy/module/cpyext/include/pythonrun.h	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/pythonrun.h	Sat Dec 18 13:29:01 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/include/structmember.h	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/include/structmember.h	Sat Dec 18 13:29:01 2010 +0100
@@ -24,17 +24,23 @@
 #define T_SHORT		0
 #define T_INT		1
 #define T_LONG		2
+#define T_FLOAT		3
+#define T_DOUBLE	4
 #define T_STRING	5
 #define T_OBJECT	6
 #define T_CHAR		7	/* 1-character string */
 #define T_BYTE		8	/* 8-bit signed int */
+#define T_UBYTE		9
 #define T_USHORT	10
 #define T_UINT		11
 #define T_ULONG		12
-#define T_STRING_INPLACE 13     /* Strings contained in the structure */
+#define T_STRING_INPLACE 13	/* Strings contained in the structure */
+#define T_BOOL		14
 #define T_OBJECT_EX	16	/* Like T_OBJECT, but raises AttributeError
 				   when the value is NULL, instead of
 				   converting to None. */
+#define T_LONGLONG	17
+#define T_ULONGLONG	 18
 
 /* Flags */
 #define READONLY      1


--- a/pypy/module/cpyext/intobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/intobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -1,9 +1,10 @@
 
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.interpreter.error import OperationError
-from pypy.module.cpyext.api import (cpython_api, PyObject, CANNOT_FAIL,
-                                    build_type_checkers, Py_ssize_t)
-
+from pypy.module.cpyext.api import (
+    cpython_api, build_type_checkers, PyObject,
+    CONST_STRING, CANNOT_FAIL, Py_ssize_t)
+from pypy.rlib.rarithmetic import r_uint
 
 PyInt_Check, PyInt_CheckExact = build_type_checkers("Int")
 
@@ -35,6 +36,20 @@
                              space.wrap("an integer is required, got NULL"))
     return space.uint_w(space.int(w_obj))
 
+ at cpython_api([PyObject], rffi.ULONG, error=-1)
+def PyInt_AsUnsignedLongMask(space, w_obj):
+    """Will first attempt to cast the object to a PyIntObject or
+    PyLongObject, if it is not already one, and then return its value as
+    unsigned long.  This function does not check for overflow.
+    """
+    w_int = space.int(w_obj)
+    if space.is_true(space.isinstance(w_int, space.w_int)):
+        num = space.int_w(w_int)
+        return r_uint(num)
+    else:
+        num = space.bigint_w(w_int)
+        return num.uintmask()
+
 @cpython_api([PyObject], lltype.Signed, error=CANNOT_FAIL)
 def PyInt_AS_LONG(space, w_int):
     """Return the value of the object w_int. No error checking is performed."""
@@ -58,3 +73,25 @@
     returned.
     """
     return space.wrap(ival) # XXX this is wrong on win64
+
+ at cpython_api([CONST_STRING, rffi.CCHARPP, rffi.INT_real], PyObject)
+def PyInt_FromString(space, str, pend, base):
+    """Return a new PyIntObject or PyLongObject based on the string
+    value in str, which is interpreted according to the radix in base.  If
+    pend is non-NULL, *pend will point to the first character in str which
+    follows the representation of the number.  If base is 0, the radix will be
+    determined based on the leading characters of str: if str starts with
+    '0x' or '0X', radix 16 will be used; if str starts with '0', radix
+    8 will be used; otherwise radix 10 will be used.  If base is not 0, it
+    must be between 2 and 36, inclusive.  Leading spaces are ignored.  If
+    there are no digits, ValueError will be raised.  If the string represents
+    a number too large to be contained within the machine's long int type
+    and overflow warnings are being suppressed, a PyLongObject will be
+    returned.  If overflow warnings are not being suppressed, NULL will be
+    returned in this case."""
+    s = rffi.charp2str(str)
+    w_str = space.wrap(s)
+    w_base = space.wrap(rffi.cast(lltype.Signed, base))
+    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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/longobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -1,8 +1,9 @@
 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
 
 
 PyLong_Check, PyLong_CheckExact = build_type_checkers("Long")
@@ -38,6 +39,13 @@
     raised."""
     return rffi.cast(rffi.ULONG, space.uint_w(w_long))
 
+ at cpython_api([PyObject], rffi.ULONG, error=-1)
+def PyLong_AsUnsignedLongMask(space, w_long):
+    """Return a C unsigned long from a Python long integer, without checking
+    for overflow.
+    """
+    return PyInt_AsUnsignedLongMask(space, w_long)
+
 @cpython_api([PyObject], lltype.Signed, error=-1)
 def PyLong_AsLong(space, w_long):
     """
@@ -62,6 +70,57 @@
     raised."""
     return rffi.cast(rffi.ULONGLONG, space.r_ulonglong_w(w_long))
 
+ at cpython_api([PyObject], rffi.ULONGLONG, error=-1)
+def PyLong_AsUnsignedLongLongMask(space, w_long):
+    """Will first attempt to cast the object to a PyIntObject or
+    PyLongObject, if it is not already one, and then return its value as
+    unsigned long long, without checking for overflow.
+    """
+    num = space.bigint_w(w_long)
+    return num.ulonglongmask()
+
+ at cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], lltype.Signed,
+             error=-1)
+def PyLong_AsLongAndOverflow(space, w_long, overflow_ptr):
+    """
+    Return a C long representation of the contents of pylong.  If pylong is
+    greater than LONG_MAX or less than LONG_MIN, set *overflow to 1 or -1,
+    respectively, and return -1; otherwise, set *overflow to 0.  If any other
+    exception occurs (for example a TypeError or MemoryError), then -1 will be
+    returned and *overflow will be 0."""
+    overflow_ptr[0] = rffi.cast(rffi.INT_real, 0)
+    try:
+        return space.int_w(w_long)
+    except OperationError, e:
+        if not e.match(space, space.w_OverflowError):
+            raise
+    if space.is_true(space.gt(w_long, space.wrap(0))):
+        overflow_ptr[0] = rffi.cast(rffi.INT_real, 1)
+    else:
+        overflow_ptr[0] = rffi.cast(rffi.INT_real, -1)
+    return -1
+
+ at cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], rffi.LONGLONG,
+             error=-1)
+def PyLong_AsLongLongAndOverflow(space, w_long, overflow_ptr):
+    """
+    Return a C long long representation of the contents of pylong.  If pylong is
+    greater than PY_LLONG_MAX or less than PY_LLONG_MIN, set *overflow to 1 or
+    -1, respectively, and return -1; otherwise, set *overflow to 0.  If any
+    other exception occurs (for example a TypeError or MemoryError), then -1
+    will be returned and *overflow will be 0."""
+    overflow_ptr[0] = rffi.cast(rffi.INT_real, 0)
+    try:
+        return rffi.cast(rffi.LONGLONG, space.r_longlong_w(w_long))
+    except OperationError, e:
+        if not e.match(space, space.w_OverflowError):
+            raise
+    if space.is_true(space.gt(w_long, space.wrap(0))):
+        overflow_ptr[0] = rffi.cast(rffi.INT_real, 1)
+    else:
+        overflow_ptr[0] = rffi.cast(rffi.INT_real, -1)
+    return -1
+
 @cpython_api([lltype.Float], PyObject)
 def PyLong_FromDouble(space, val):
     """Return a new PyLongObject object from v, or NULL on failure."""
@@ -109,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	Sat Dec 18 13:29:01 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)


--- a/pypy/module/cpyext/methodobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/methodobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -16,13 +16,14 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.objspace.std.tupleobject import W_TupleObject
 
+PyCFunction_typedef = rffi.COpaquePtr('PyCFunction')
 PyCFunction = lltype.Ptr(lltype.FuncType([PyObject, PyObject], PyObject))
 PyCFunctionKwArgs = lltype.Ptr(lltype.FuncType([PyObject, PyObject, PyObject], PyObject))
 
 PyMethodDef = cpython_struct(
     'PyMethodDef',
     [('ml_name', rffi.CCHARP),
-     ('ml_meth', PyCFunction),
+     ('ml_meth', PyCFunction_typedef),
      ('ml_flags', rffi.INT_real),
      ('ml_doc', rffi.CCHARP),
      ])
@@ -70,12 +71,14 @@
         if space.is_true(w_kw) and not flags & METH_KEYWORDS:
             raise OperationError(space.w_TypeError, space.wrap(
                 rffi.charp2str(self.ml.c_ml_name) + "() takes no keyword arguments"))
+
+        func = rffi.cast(PyCFunction, self.ml.c_ml_meth)
         if flags & METH_KEYWORDS:
             func = rffi.cast(PyCFunctionKwArgs, self.ml.c_ml_meth)
             return generic_cpy_call(space, func, w_self, w_args, w_kw)
         elif flags & METH_NOARGS:
             if len(w_args.wrappeditems) == 0:
-                return generic_cpy_call(space, self.ml.c_ml_meth, w_self, None)
+                return generic_cpy_call(space, func, w_self, None)
             raise OperationError(space.w_TypeError, space.wrap(
                 rffi.charp2str(self.ml.c_ml_name) + "() takes no arguments"))
         elif flags & METH_O:
@@ -86,9 +89,9 @@
                         rffi.charp2str(self.ml.c_ml_name), 
                         len(w_args.wrappeditems))))
             w_arg = w_args.wrappeditems[0]
-            return generic_cpy_call(space, self.ml.c_ml_meth, w_self, w_arg)
+            return generic_cpy_call(space, func, w_self, w_arg)
         elif flags & METH_VARARGS:
-            return generic_cpy_call(space, self.ml.c_ml_meth, w_self, w_args)
+            return generic_cpy_call(space, func, w_self, w_args)
         else: # METH_OLDARGS, the really old style
             size = len(w_args.wrappeditems)
             if size == 1:
@@ -97,7 +100,7 @@
                 w_arg = None
             else:
                 w_arg = w_args
-            return generic_cpy_call(space, self.ml.c_ml_meth, w_self, w_arg)
+            return generic_cpy_call(space, func, w_self, w_arg)
 
     def get_doc(space, self):
         doc = self.ml.c_ml_doc
@@ -231,6 +234,11 @@
 def PyCFunction_NewEx(space, ml, w_self, w_name):
     return space.wrap(W_PyCFunctionObject(space, ml, w_self, w_name))
 
+ at cpython_api([PyObject], PyCFunction_typedef)
+def PyCFunction_GetFunction(space, w_obj):
+    cfunction = space.interp_w(W_PyCFunctionObject, w_obj)
+    return cfunction.ml.c_ml_meth
+
 @cpython_api([PyObject], PyObject)
 def PyStaticMethod_New(space, w_func):
     return space.wrap(StaticMethod(w_func))


--- a/pypy/module/cpyext/modsupport.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/modsupport.py	Sat Dec 18 13:29:01 2010 +0100
@@ -5,7 +5,7 @@
 from pypy.interpreter.module import Module
 from pypy.module.cpyext.methodobject import (
     W_PyCFunctionObject, PyCFunction_NewEx, PyDescr_NewMethod,
-    PyMethodDef, PyCFunction, PyStaticMethod_New)
+    PyMethodDef, PyStaticMethod_New)
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 from pypy.module.cpyext.state import State
 from pypy.interpreter.error import OperationError


--- a/pypy/module/cpyext/object.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/object.py	Sat Dec 18 13:29:01 2010 +0100
@@ -15,7 +15,7 @@
 import pypy.module.__builtin__.operation as operation
 
 
- at cpython_api([Py_ssize_t], rffi.VOIDP, error=lltype.nullptr(rffi.VOIDP.TO))
+ at cpython_api([Py_ssize_t], rffi.VOIDP)
 def PyObject_MALLOC(space, size):
     return lltype.malloc(rffi.VOIDP.TO, size,
                          flavor='raw', zero=True)


--- a/pypy/module/cpyext/pyerrors.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/pyerrors.py	Sat Dec 18 13:29:01 2010 +0100
@@ -275,3 +275,12 @@
 def PyErr_Print(space):
     """Alias for PyErr_PrintEx(1)."""
     PyErr_PrintEx(space, 1)
+
+ at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
+def PyTraceBack_Print(space, w_tb, w_file):
+    space.call_method(w_file, "write", space.wrap(
+        'Traceback (most recent call last):\n'))
+    w_traceback = space.call_method(space.builtin, '__import__',
+                                    space.wrap("traceback"))
+    space.call_method(w_traceback, "print_tb", w_tb, space.w_None, w_file)
+    return 0


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/src/capsule.c	Sat Dec 18 13:29:01 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/getargs.c	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/src/getargs.c	Sat Dec 18 13:29:01 2010 +0100
@@ -558,8 +558,6 @@
 	switch (c) {
 	
 	case 'b': { /* unsigned byte -- very short int */
-    Py_FatalError("'b' unimplemented for PyArg_*\n");
-#if 0
 		char *p = va_arg(*p_va, char *);
 		long ival;
 		if (float_argument_error(arg))
@@ -580,13 +578,10 @@
 		else
 			*p = (unsigned char) ival;
 		break;
-#endif
 	}
 	
 	case 'B': {/* byte sized bitfield - both signed and unsigned
 		      values allowed */  
-    Py_FatalError("'B' unimplemented for PyArg_*\n");
-#if 0
 		char *p = va_arg(*p_va, char *);
 		long ival;
 		if (float_argument_error(arg))
@@ -597,12 +592,9 @@
 		else
 			*p = (unsigned char) ival;
 		break;
-#endif
 	}
 	
 	case 'h': {/* signed short int */
-    Py_FatalError("'h' unimplemented for PyArg_*\n");
-#if 0
 		short *p = va_arg(*p_va, short *);
 		long ival;
 		if (float_argument_error(arg))
@@ -623,13 +615,10 @@
 		else
 			*p = (short) ival;
 		break;
-#endif
 	}
 	
 	case 'H': { /* short int sized bitfield, both signed and
 		       unsigned allowed */ 
-    Py_FatalError("'H' unimplemented for PyArg_*\n");
-#if 0
 		unsigned short *p = va_arg(*p_va, unsigned short *);
 		long ival;
 		if (float_argument_error(arg))
@@ -640,7 +629,6 @@
 		else
 			*p = (unsigned short) ival;
 		break;
-#endif
 	}
 	case 'i': {/* signed int */
 		int *p = va_arg(*p_va, int *);
@@ -666,8 +654,6 @@
 	}
 	case 'I': { /* int sized bitfield, both signed and
 		       unsigned allowed */ 
-    Py_FatalError("'I' unimplemented for PyArg_*\n");
-#if 0
 		unsigned int *p = va_arg(*p_va, unsigned int *);
 		unsigned int ival;
 		if (float_argument_error(arg))
@@ -678,7 +664,6 @@
 		else
 			*p = ival;
 		break;
-#endif	
 	}
 	case 'n': /* Py_ssize_t */
 #if SIZEOF_SIZE_T != SIZEOF_LONG
@@ -709,8 +694,6 @@
 	}
 
 	case 'k': { /* long sized bitfield */
-    Py_FatalError("'k' unimplemented for PyArg_*\n");
-#if 0
 		unsigned long *p = va_arg(*p_va, unsigned long *);
 		unsigned long ival;
 		if (PyInt_Check(arg))
@@ -721,13 +704,10 @@
 			return converterr("integer<k>", arg, msgbuf, bufsize);
 		*p = ival;
 		break;
-#endif
 	}
 	
 #ifdef HAVE_LONG_LONG
 	case 'L': {/* PY_LONG_LONG */
-    Py_FatalError("'L' unimplemented for PyArg_*\n");
-#if 0
 		PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * );
 		PY_LONG_LONG ival = PyLong_AsLongLong( arg );
 		if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) {
@@ -736,12 +716,9 @@
 			*p = ival;
 		}
 		break;
-#endif
 	}
 
 	case 'K': { /* long long sized bitfield */
-    Py_FatalError("'K' unimplemented for PyArg_*\n");
-#if 0
 		unsigned PY_LONG_LONG *p = va_arg(*p_va, unsigned PY_LONG_LONG *);
 		unsigned PY_LONG_LONG ival;
 		if (PyInt_Check(arg))
@@ -752,7 +729,6 @@
 			return converterr("integer<K>", arg, msgbuf, bufsize);
 		*p = ival;
 		break;
-#endif	
   }
 #endif // HAVE_LONG_LONG
 
@@ -778,8 +754,6 @@
 	
 #ifndef WITHOUT_COMPLEX
 	case 'D': {/* complex double */
-    Py_FatalError("'D' unimplemented for PyArg_*\n");
-#if 0
 		Py_complex *p = va_arg(*p_va, Py_complex *);
 		Py_complex cval;
 		cval = PyComplex_AsCComplex(arg);
@@ -788,7 +762,6 @@
 		else
 			*p = cval;
 		break;
-#endif
 	}
 #endif /* WITHOUT_COMPLEX */
 	
@@ -986,8 +959,6 @@
 		break;
 	}
 	case 'e': {/* encoded string */
-    Py_FatalError("'e' unimplemented for PyArg_*\n");
-#if 0
 		char **buffer;
 		const char *encoding;
 		PyObject *s;
@@ -1151,7 +1122,6 @@
 		}
 		Py_DECREF(s);
 		break;
-#endif
 	}
 
 #ifdef Py_USING_UNICODE


--- a/pypy/module/cpyext/src/pyerrors.c	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/src/pyerrors.c	Sat Dec 18 13:29:01 2010 +0100
@@ -69,3 +69,37 @@
 	Py_XDECREF(modulename);
 	return result;
 }
+
+/* Create an exception with docstring */
+PyObject *
+PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict)
+{
+    int result;
+    PyObject *ret = NULL;
+    PyObject *mydict = NULL; /* points to the dict only if we create it */
+    PyObject *docobj;
+
+    if (dict == NULL) {
+        dict = mydict = PyDict_New();
+        if (dict == NULL) {
+            return NULL;
+        }
+    }
+
+    if (doc != NULL) {
+        docobj = PyString_FromString(doc);
+        if (docobj == NULL)
+            goto failure;
+        result = PyDict_SetItemString(dict, "__doc__", docobj);
+        Py_DECREF(docobj);
+        if (result < 0)
+            goto failure;
+    }
+
+    ret = PyErr_NewException(name, base, dict);
+  failure:
+    Py_XDECREF(mydict);
+    return ret;
+}
+
+


--- a/pypy/module/cpyext/src/structseq.c	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/src/structseq.c	Sat Dec 18 13:29:01 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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/state.py	Sat Dec 18 13:29:01 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/structmember.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/structmember.py	Sat Dec 18 13:29:01 2010 +0100
@@ -1,64 +1,77 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext import structmemberdefs
+from pypy.module.cpyext.structmemberdefs import *
 from pypy.module.cpyext.api import ADDR, PyObjectP, cpython_api
 from pypy.module.cpyext.intobject import PyInt_AsLong, PyInt_AsUnsignedLong
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, from_ref, make_ref
-from pypy.module.cpyext.stringobject import (PyString_FromString,
-                                             PyString_FromStringAndSize)
+from pypy.module.cpyext.stringobject import (
+    PyString_FromString, PyString_FromStringAndSize)
+from pypy.module.cpyext.floatobject import PyFloat_AsDouble
+from pypy.module.cpyext.longobject import (
+    PyLong_AsLongLong, PyLong_AsUnsignedLongLong)
 from pypy.module.cpyext.typeobjectdefs import PyMemberDef
+from pypy.rlib.unroll import unrolling_iterable
+
+integer_converters = unrolling_iterable([
+    (T_SHORT,  rffi.SHORT,  PyInt_AsLong),
+    (T_INT,    rffi.INT,    PyInt_AsLong),
+    (T_LONG,   rffi.LONG,   PyInt_AsLong),
+    (T_USHORT, rffi.USHORT, PyInt_AsUnsignedLong),
+    (T_UINT,   rffi.UINT,   PyInt_AsUnsignedLong),
+    (T_ULONG,  rffi.ULONG,  PyInt_AsUnsignedLong),
+    (T_BYTE,   rffi.UCHAR,  PyInt_AsLong),
+    (T_UBYTE,  rffi.UCHAR,  PyInt_AsUnsignedLong),
+    (T_BOOL,   rffi.UCHAR,  PyInt_AsLong),
+    (T_FLOAT,  rffi.FLOAT,  PyFloat_AsDouble),
+    (T_DOUBLE, rffi.DOUBLE, PyFloat_AsDouble),
+    (T_LONGLONG,  rffi.LONGLONG,  PyLong_AsLongLong),
+    (T_ULONGLONG, rffi.ULONGLONG, PyLong_AsUnsignedLongLong),
+    ])
 
 
 @cpython_api([PyObject, lltype.Ptr(PyMemberDef)], PyObject)
 def PyMember_GetOne(space, obj, w_member):
     addr = rffi.cast(ADDR, obj)
     addr += w_member.c_offset
+
     member_type = rffi.cast(lltype.Signed, w_member.c_type)
-    if member_type == structmemberdefs.T_SHORT:
-        result = rffi.cast(rffi.SHORTP, addr)
-        w_result = space.wrap(result[0])
-    elif member_type == structmemberdefs.T_INT:
-        result = rffi.cast(rffi.INTP, addr)
-        w_result = space.wrap(result[0])
-    elif member_type == structmemberdefs.T_LONG:
-        result = rffi.cast(rffi.LONGP, addr)
-        w_result = space.wrap(result[0])
-    elif member_type == structmemberdefs.T_USHORT:
-        result = rffi.cast(rffi.USHORTP, addr)
-        w_result = space.wrap(result[0])
-    elif member_type == structmemberdefs.T_UINT:
-        result = rffi.cast(rffi.UINTP, addr)
-        w_result = space.wrap(result[0])
-    elif member_type == structmemberdefs.T_ULONG:
-        result = rffi.cast(rffi.ULONGP, addr)
-        w_result = space.wrap(result[0])
-    elif member_type == structmemberdefs.T_BYTE:
-        result = rffi.cast(rffi.CCHARP, addr)
-        w_result = space.wrap(result[0])
-    elif member_type == structmemberdefs.T_STRING:
+    for converter in integer_converters:
+        typ, lltyp, _ = converter
+        if typ == member_type:
+            result = rffi.cast(rffi.CArrayPtr(lltyp), addr)
+            if lltyp is rffi.FLOAT:
+                w_result = space.wrap(rffi.cast(rffi.DOUBLE, result[0]))
+            else:
+                w_result = space.wrap(result[0])
+            return w_result
+
+    if member_type == T_STRING:
         result = rffi.cast(rffi.CCHARPP, addr)
         if result[0]:
             w_result = PyString_FromString(space, result[0])
         else:
             w_result = space.w_None
-    elif member_type == structmemberdefs.T_STRING_INPLACE:
+    elif member_type == T_STRING_INPLACE:
         result = rffi.cast(rffi.CCHARP, addr)
         w_result = PyString_FromString(space, result)
-    elif member_type == structmemberdefs.T_CHAR:
+    elif member_type == T_CHAR:
         result = rffi.cast(rffi.CCHARP, addr)
         w_result = space.wrap(result[0])
-    elif member_type in [structmemberdefs.T_OBJECT,
-                         structmemberdefs.T_OBJECT_EX]:
+    elif member_type == T_OBJECT:
         obj_ptr = rffi.cast(PyObjectP, addr)
         if obj_ptr[0]:
             w_result = from_ref(space, obj_ptr[0])
         else:
-            if member_type == structmemberdefs.T_OBJECT_EX:
-                w_name = space.wrap(rffi.charp2str(w_member.c_name))
-                raise OperationError(space.w_AttributeError, w_name)
             w_result = space.w_None
+    elif member_type == T_OBJECT_EX:
+        obj_ptr = rffi.cast(PyObjectP, addr)
+        if obj_ptr[0]:
+            w_result = from_ref(space, obj_ptr[0])
+        else:
+            w_name = space.wrap(rffi.charp2str(w_member.c_name))
+            raise OperationError(space.w_AttributeError, w_name)
     else:
         raise OperationError(space.w_SystemError,
                              space.wrap("bad memberdescr type"))
@@ -72,57 +85,35 @@
     member_type = rffi.cast(lltype.Signed, w_member.c_type)
     flags = rffi.cast(lltype.Signed, w_member.c_flags)
 
-    if (flags & structmemberdefs.READONLY or
-        member_type in [structmemberdefs.T_STRING,
-                        structmemberdefs.T_STRING_INPLACE]):
+    if (flags & READONLY or
+        member_type in [T_STRING, T_STRING_INPLACE]):
         raise OperationError(space.w_TypeError,
                              space.wrap("readonly attribute"))
     elif w_value is None:
-        if member_type == structmemberdefs.T_OBJECT_EX:
+        if member_type == T_OBJECT_EX:
             if not rffi.cast(PyObjectP, addr)[0]:
                 w_name = space.wrap(rffi.charp2str(w_member.c_name))
                 raise OperationError(space.w_AttributeError, w_name)
-        elif member_type != structmemberdefs.T_OBJECT:
+        elif member_type != T_OBJECT:
             raise OperationError(space.w_TypeError,
                              space.wrap("can't delete numeric/char attribute"))
 
-    if member_type == structmemberdefs.T_SHORT:
-        w_long_value = PyInt_AsLong(space, w_value)
-        array = rffi.cast(rffi.SHORTP, addr)
-        array[0] = rffi.cast(rffi.SHORT, w_long_value)
-    elif member_type == structmemberdefs.T_INT:
-        w_long_value = PyInt_AsLong(space, w_value)
-        array = rffi.cast(rffi.INTP, addr)
-        array[0] = rffi.cast(rffi.INT, w_long_value)
-    elif member_type == structmemberdefs.T_LONG:
-        w_long_value = PyInt_AsLong(space, w_value)
-        array = rffi.cast(rffi.LONGP, addr)
-        array[0] = rffi.cast(rffi.LONG, w_long_value)
-    elif member_type == structmemberdefs.T_USHORT:
-        w_long_value = PyInt_AsUnsignedLong(space, w_value)
-        array = rffi.cast(rffi.USHORTP, addr)
-        array[0] = rffi.cast(rffi.USHORT, w_long_value)
-    elif member_type == structmemberdefs.T_UINT:
-        w_long_value = PyInt_AsUnsignedLong(space, w_value)
-        array = rffi.cast(rffi.UINTP, addr)
-        array[0] = rffi.cast(rffi.UINT, w_long_value)
-    elif member_type == structmemberdefs.T_ULONG:
-        w_long_value = PyInt_AsUnsignedLong(space, w_value)
-        array = rffi.cast(rffi.ULONGP, addr)
-        array[0] = rffi.cast(rffi.ULONG, w_long_value)
-    elif member_type == structmemberdefs.T_BYTE:
-        w_long_value = PyInt_AsLong(space, w_value)
-        array = rffi.cast(rffi.CCHARP, addr)
-        array[0] = rffi.cast(rffi.CHAR, w_long_value)
-    elif member_type == structmemberdefs.T_CHAR:
+    for converter in integer_converters:
+        typ, lltyp, getter = converter
+        if typ == member_type:
+            value = getter(space, w_value)
+            array = rffi.cast(rffi.CArrayPtr(lltyp), addr)
+            array[0] = rffi.cast(lltyp, value)
+            return 0
+
+    if member_type == T_CHAR:
         str_value = space.str_w(w_value)
         if len(str_value) != 1:
             raise OperationError(space.w_TypeError,
                                  space.wrap("string of length 1 expected"))
         array = rffi.cast(rffi.CCHARP, addr)
         array[0] = str_value[0]
-    elif member_type in [structmemberdefs.T_OBJECT,
-                         structmemberdefs.T_OBJECT_EX]:
+    elif member_type in [T_OBJECT, T_OBJECT_EX]:
         array = rffi.cast(PyObjectP, addr)
         if array[0]:
             Py_DecRef(space, array[0])


--- a/pypy/module/cpyext/structmemberdefs.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/structmemberdefs.py	Sat Dec 18 13:29:01 2010 +0100
@@ -1,14 +1,20 @@
 T_SHORT = 0
 T_INT = 1
 T_LONG = 2
+T_FLOAT = 3
+T_DOUBLE = 4
 T_STRING = 5
 T_OBJECT = 6
 T_CHAR = 7
 T_BYTE = 8
+T_UBYTE = 9
 T_USHORT = 10
 T_UINT = 11
 T_ULONG = 12
 T_STRING_INPLACE = 13
+T_BOOL = 14
 T_OBJECT_EX = 16
+T_LONGLONG = 17
+T_ULONGLONG = 18
 
 READONLY = RO = 1


--- a/pypy/module/cpyext/stubs.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/stubs.py	Sat Dec 18 13:29:01 2010 +0100
@@ -4,73 +4,34 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 
 # we don't really care
-PyTypeObjectPtr = lltype.Void
-Py_ssize_t = lltype.Void
-PyMethodDef = lltype.Void
-PyGetSetDef = lltype.Void
-PyMemberDef = lltype.Void
-Py_buffer = lltype.Void
-Py_complex = lltype.Void
-va_list = lltype.Void
-PyDateTime_Date = lltype.Void
-PyDateTime_DateTime = lltype.Void
-PyDateTime_Time = lltype.Void
-wrapperbase = lltype.Void
-FILE = lltype.Void
-PyFileObject = lltype.Void
-PyCodeObject = lltype.Void
-PyFrameObject = lltype.Void
-_inittab = lltype.Void
-PyThreadState = lltype.Void
-PyInterpreterState = lltype.Void
-#PyOS_sighandler_t = lltype.Void
-Py_UNICODE = lltype.Void
-PyCompilerFlags = lltype.Void
-_node = lltype.Void
+PyTypeObjectPtr = rffi.VOIDP
+Py_ssize_t = rffi.VOIDP
+PyMethodDef = rffi.VOIDP
+PyGetSetDef = rffi.VOIDP
+PyMemberDef = rffi.VOIDP
+Py_buffer = rffi.VOIDP
+Py_complex = rffi.VOIDP
+va_list = rffi.VOIDP
+PyDateTime_Date = rffi.VOIDP
+PyDateTime_DateTime = rffi.VOIDP
+PyDateTime_Time = rffi.VOIDP
+wrapperbase = rffi.VOIDP
+FILE = rffi.VOIDP
+PyFileObject = rffi.VOIDP
+PyCodeObject = rffi.VOIDP
+PyFrameObject = rffi.VOIDP
+_inittab = rffi.VOIDP
+PyThreadState = rffi.VOIDP
+PyInterpreterState = rffi.VOIDP
+PyOS_sighandler_t = rffi.VOIDP
+Py_UNICODE = rffi.VOIDP
+PyCompilerFlags = rffi.VOIDP
+_node = rffi.VOIDP
 
 @cpython_api([PyObject], lltype.Void)
 def _PyObject_Del(space, op):
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, PyMethodDef], PyObject)
-def Py_InitModule(space, name, methods):
-    """Create a new module object based on a name and table of functions,
-    returning the new module object.
-    
-    Older versions of Python did not support NULL as the value for the
-    methods argument."""
-    borrow_from()
-    raise NotImplementedError
-
- at cpython_api([rffi.CCHARP, PyMethodDef, rffi.CCHARP], PyObject)
-def Py_InitModule3(space, name, methods, doc):
-    """Create a new module object based on a name and table of functions,
-    returning the new module object.  If doc is non-NULL, it will be used
-    to define the docstring for the module.
-    
-    Older versions of Python did not support NULL as the value for the
-    methods argument."""
-    borrow_from()
-    raise NotImplementedError
-
- at cpython_api([PyObject, rffi.CCHARP, va_list], rffi.INT_real, error=0)
-def PyArg_VaParse(space, args, format, vargs):
-    """Identical to PyArg_ParseTuple(), except that it accepts a va_list
-    rather than a variable number of arguments."""
-    raise NotImplementedError
-
- at cpython_api([PyObject, PyObject, rffi.CCHARP, rffi.CCHARP, va_list], rffi.INT_real, error=0)
-def PyArg_VaParseTupleAndKeywords(space, args, kw, format, keywords, vargs):
-    """Identical to PyArg_ParseTupleAndKeywords(), except that it accepts a
-    va_list rather than a variable number of arguments."""
-    raise NotImplementedError
-
- at cpython_api([rffi.CCHARP, va_list], PyObject)
-def Py_VaBuildValue(space, format, vargs):
-    """Identical to Py_BuildValue(), except that it accepts a va_list
-    rather than a variable number of arguments."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=0)
 def PyObject_CheckBuffer(space, obj):
     """Return 1 if obj supports the buffer interface otherwise 0."""
@@ -261,11 +222,6 @@
     length.  Return 0 on success and -1 (with raising an error) on error."""
     raise NotImplementedError
 
- at cpython_api([PyObject], PyObject)
-def PyMemoryView_FromObject(space, obj):
-    """Return a memoryview object from an object that defines the buffer interface."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyByteArray_Check(space, o):
     """Return true if the object o is a bytearray object or an instance of a
@@ -372,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"""
@@ -402,13 +346,6 @@
     version since the definition of the bytecode changes often."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject)
-def PyCode_NewEmpty(space, filename, funcname, firstlineno):
-    """Return a new empty code object with the specified filename,
-    function name, and first line number.  It is illegal to
-    exec or eval() the resulting code object."""
-    raise NotImplementedError
-
 @cpython_api([Py_complex, Py_complex], Py_complex)
 def _Py_c_sum(space, left, right):
     """Return the sum of two complex numbers, using the C Py_complex
@@ -627,14 +564,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
-def PyDict_Contains(space, p, key):
-    """Determine if dictionary p contains key.  If an item in p is matches
-    key, return 1, otherwise return 0.  On error, return -1.
-    This is equivalent to the Python expression key in p.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject, rffi.CCHARP], rffi.INT_real, error=-1)
 def PyDict_DelItemString(space, p, key):
     """Remove the entry in dictionary p which has a key specified by the string
@@ -716,13 +645,6 @@
     described there."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, rffi.INT_real], rffi.INT_real, error=-1)
-def PyErr_WarnPy3k(space, message, stacklevel):
-    """Issue a DeprecationWarning with the given message and stacklevel
-    if the Py_Py3kWarningFlag flag is enabled.
-    """
-    raise NotImplementedError
-
 @cpython_api([], lltype.Void)
 def PyErr_SetInterrupt(space, ):
     """
@@ -748,14 +670,6 @@
     only be called from the main thread."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, rffi.CCHARP, PyObject, PyObject], PyObject)
-def PyErr_NewExceptionWithDoc(space, name, doc, base, dict):
-    """Same as PyErr_NewException(), except that the new exception class can
-    easily be given a docstring: If doc is non-NULL, it will be used as the
-    docstring for the exception class.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject], lltype.Void)
 def PyErr_WriteUnraisable(space, obj):
     """This utility function prints a warning message to sys.stderr when an
@@ -879,13 +793,6 @@
     failure; the appropriate exception will be set."""
     raise NotImplementedError
 
- at cpython_api([PyObject, rffi.CCHARPP], PyObject)
-def PyFloat_FromString(space, str, pend):
-    """Create a PyFloatObject object based on the string value in str, or
-    NULL on failure.  The pend argument is ignored.  It remains only for
-    backward compatibility."""
-    raise NotImplementedError
-
 @cpython_api([rffi.VOIDP_real], PyObject)
 def PyFloat_GetInfo(space, info):
     """Return a structseq instance which contains information about the
@@ -1024,22 +931,6 @@
     extension modules."""
     raise NotImplementedError
 
- at cpython_api([PyObject], lltype.Void)
-def Py_VISIT(space, o):
-    """Call the visit callback, with arguments o and arg. If visit returns
-    a non-zero value, then return it.  Using this macro, tp_traverse
-    handlers look like:
-    
-    static int
-    my_traverse(Noddy *self, visitproc visit, void *arg)
-    {
-        Py_VISIT(self->foo);
-        Py_VISIT(self->bar);
-        return 0;
-    }
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyGen_Check(space, gen):
     """Return true if ob is a generator object; ob must not be NULL."""
@@ -1058,18 +949,6 @@
     NULL."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP], PyObject)
-def PyImport_ImportModuleNoBlock(space, name):
-    """This version of PyImport_ImportModule() does not block. It's intended
-    to be used in C functions that import other modules to execute a function.
-    The import may block if another thread holds the import lock. The function
-    PyImport_ImportModuleNoBlock() never blocks. It first tries to fetch
-    the module from sys.modules and falls back to PyImport_ImportModule()
-    unless the lock is held, in which case the function will raise an
-    ImportError.
-    """
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, PyObject, PyObject, PyObject], PyObject)
 def PyImport_ImportModuleEx(space, name, globals, locals, fromlist):
     """
@@ -1789,23 +1668,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, rffi.CCHARPP, rffi.INT_real], PyObject)
-def PyInt_FromString(space, str, pend, base):
-    """Return a new PyIntObject or PyLongObject based on the string
-    value in str, which is interpreted according to the radix in base.  If
-    pend is non-NULL, *pend will point to the first character in str which
-    follows the representation of the number.  If base is 0, the radix will be
-    determined based on the leading characters of str: if str starts with
-    '0x' or '0X', radix 16 will be used; if str starts with '0', radix
-    8 will be used; otherwise radix 10 will be used.  If base is not 0, it
-    must be between 2 and 36, inclusive.  Leading spaces are ignored.  If
-    there are no digits, ValueError will be raised.  If the string represents
-    a number too large to be contained within the machine's long int type
-    and overflow warnings are being suppressed, a PyLongObject will be
-    returned.  If overflow warnings are not being suppressed, NULL will be
-    returned in this case."""
-    raise NotImplementedError
-
 @cpython_api([rffi.SIZE_T], PyObject)
 def PyInt_FromSize_t(space, ival):
     """Create a new integer object with a value of ival. If the value exceeds
@@ -1813,22 +1675,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject], rffi.ULONG, error=-1)
-def PyInt_AsUnsignedLongMask(space, io):
-    """Will first attempt to cast the object to a PyIntObject or
-    PyLongObject, if it is not already one, and then return its value as
-    unsigned long.  This function does not check for overflow.
-    """
-    raise NotImplementedError
-
- at cpython_api([PyObject], rffi.LONGLONG, error=-1)
-def PyInt_AsUnsignedLongLongMask(space, io):
-    """Will first attempt to cast the object to a PyIntObject or
-    PyLongObject, if it is not already one, and then return its value as
-    unsigned long long, without checking for overflow.
-    """
-    raise NotImplementedError
-
 @cpython_api([], lltype.Signed, error=CANNOT_FAIL)
 def PyInt_GetMax(space, ):
     """
@@ -1855,29 +1701,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, Py_ssize_t], PyObject)
-def PyList_GET_ITEM(space, list, i):
-    """Macro form of PyList_GetItem() without error checking.
-    
-    This macro used an int for i. This might require changes in
-    your code for properly supporting 64-bit systems."""
-    borrow_from()
-    raise NotImplementedError
-
- at cpython_api([PyObject, Py_ssize_t, PyObject], lltype.Void)
-def PyList_SET_ITEM(space, list, i, o):
-    """Macro form of PyList_SetItem() without error checking. This is
-    normally only used to fill in new lists where there is no previous content.
-    
-    This macro "steals" a reference to item, and, unlike
-    PyList_SetItem(), does not discard a reference to any item that
-    it being replaced; any reference in list at position i will be
-    leaked.
-    
-    This macro used an int for i. This might require
-    changes in your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
 @cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
 def PyList_GetSlice(space, list, low, high):
     """Return a list of the objects in list containing the objects between low
@@ -1917,30 +1740,6 @@
     changes in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
- at cpython_api([PyObject, rffi.INTP], lltype.Signed, error=-1)
-def PyLong_AsLongAndOverflow(space, pylong, overflow):
-    """Return a C long representation of the contents of
-    pylong.  If pylong is greater than LONG_MAX or less
-    than LONG_MIN, set *overflow to 1 or -1,
-    respectively, and return -1; otherwise, set *overflow to
-    0.  If any other exception occurs (for example a TypeError or
-    MemoryError), then -1 will be returned and *overflow will
-    be 0.
-    """
-    raise NotImplementedError
-
- at cpython_api([PyObject, rffi.INTP], rffi.LONGLONG, error=-1)
-def PyLong_AsLongLongAndOverflow(space, pylong, overflow):
-    """Return a C long long representation of the contents of
-    pylong.  If pylong is greater than PY_LLONG_MAX or less
-    than PY_LLONG_MIN, set *overflow to 1 or -1,
-    respectively, and return -1; otherwise, set *overflow to
-    0.  If any other exception occurs (for example a TypeError or
-    MemoryError), then -1 will be returned and *overflow will
-    be 0.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject], Py_ssize_t)
 def PyLong_AsSsize_t(space, pylong):
     """
@@ -1953,20 +1752,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject], rffi.ULONG, error=-1)
-def PyLong_AsUnsignedLongMask(space, io):
-    """Return a C unsigned long from a Python long integer, without checking
-    for overflow.
-    """
-    raise NotImplementedError
-
- at cpython_api([PyObject], rffi.ULONGLONG, error=-1)
-def PyLong_AsUnsignedLongLongMask(space, io):
-    """Return a C unsigned long long from a Python long integer, without
-    checking for overflow.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject, rffi.CCHARP], rffi.INT_real, error=-1)
 def PyMapping_DelItemString(space, o, key):
     """Remove the mapping for object key from the object o. Return -1 on
@@ -2398,20 +2183,6 @@
     changes in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
- at cpython_api([PyObject], Py_ssize_t)
-def PyString_GET_SIZE(space, string):
-    """Macro form of PyString_Size() but without error checking.
-    
-    This macro returned an int type. This might require changes in
-    your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
- at cpython_api([PyObject], rffi.CCHARP, error=CANNOT_FAIL)
-def PyString_AS_STRING(space, string):
-    """Macro form of PyString_AsString() but without error checking.  Only
-    string objects are supported; no Unicode objects should be passed."""
-    raise NotImplementedError
-
 @cpython_api([PyObjectP], lltype.Void)
 def PyString_InternInPlace(space, string):
     """Intern the argument *string in place.  The argument must be the address of a
@@ -2590,15 +2361,6 @@
     the cleanup function, no Python APIs should be called by func."""
     raise NotImplementedError
 
- at cpython_api([PyObject, Py_ssize_t], PyObject)
-def PyTuple_GET_ITEM(space, p, pos):
-    """Like PyTuple_GetItem(), but does no checking of its arguments.
-    
-    This function used an int type for pos. This might require
-    changes in your code for properly supporting 64-bit systems."""
-    borrow_from()
-    raise NotImplementedError
-
 @cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject)
 def PyTuple_GetSlice(space, p, low, high):
     """Take a slice of the tuple pointed to by p from low to high and return it
@@ -2608,17 +2370,6 @@
     require changes in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
- at cpython_api([PyObject, Py_ssize_t, PyObject], lltype.Void)
-def PyTuple_SET_ITEM(space, p, pos, o):
-    """Like PyTuple_SetItem(), but does no error checking, and should only be
-    used to fill in brand new tuples.
-    
-    This function "steals" a reference to o.
-    
-    This function used an int type for pos. This might require
-    changes in your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
 @cpython_api([], rffi.INT_real, error=CANNOT_FAIL)
 def PyTuple_ClearFreeList(space, ):
     """Clear the free list. Return the total number of freed items.
@@ -2639,12 +2390,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, rffi.INT_real], rffi.INT_real, error=CANNOT_FAIL)
-def PyType_HasFeature(space, o, feature):
-    """Return true if the type object o sets the feature feature.  Type features
-    are denoted by single bit flags."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def PyType_IS_GC(space, o):
     """Return true if the type object includes support for the cycle detector; this
@@ -2701,12 +2446,6 @@
     possible.  This macro does not raise exceptions."""
     raise NotImplementedError
 
- at cpython_api([PyObject], PyObject)
-def PyUnicode_FromObject(space, obj):
-    """Shortcut for PyUnicode_FromEncodedObject(obj, NULL, "strict") which is used
-    throughout the interpreter whenever coercion to Unicode is needed."""
-    raise NotImplementedError
-
 @cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP, rffi.CCHARP], PyObject)
 def PyUnicode_Encode(space, s, size, encoding, errors):
     """Encode the Py_UNICODE buffer of the given size and return a Python
@@ -3093,12 +2832,6 @@
     require changes in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject], rffi.INT_real, error=-2)
-def PyUnicode_Compare(space, left, right):
-    """Compare two strings and return -1, 0, 1 for less than, equal, and greater than,
-    respectively."""
-    raise NotImplementedError
-
 @cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
 def PyUnicode_RichCompare(space, left, right, op):
     """Rich compare two unicode strings and return one of the following:


--- a/pypy/module/cpyext/test/conftest.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/conftest.py	Sat Dec 18 13:29:01 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	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_api.py	Sat Dec 18 13:29:01 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	Sat Dec 18 13:29:01 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


--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pypy/module/cpyext/test/test_codecs.py	Sat Dec 18 13:29:01 2010 +0100
@@ -0,0 +1,14 @@
+# encoding: iso-8859-15
+from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.rpython.lltypesystem import rffi, lltype
+
+class TestCodecs(BaseApiTest):
+    def test_incremental(self, space, api):
+        utf8 = rffi.str2charp('utf-8')
+        w_encoder = api.PyCodec_IncrementalEncoder(utf8, None)
+        w_encoded = space.call_method(w_encoder, 'encode', space.wrap(u'späm'))
+        w_decoder = api.PyCodec_IncrementalDecoder(utf8, None)
+        w_decoded = space.call_method(w_decoder, 'decode', w_encoded)
+        assert space.unwrap(w_decoded) == u'späm'
+        rffi.free_charp(utf8)
+


--- a/pypy/module/cpyext/test/test_cpyext.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_cpyext.py	Sat Dec 18 13:29:01 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_dictobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_dictobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -29,6 +29,9 @@
         rffi.free_charp(buf)
         assert not api.PyErr_Occurred()
 
+        assert api.PyDict_Contains(d, space.wrap("c"))
+        assert not api.PyDict_Contains(d, space.wrap("z"))
+
         assert api.PyDict_DelItem(d, space.wrap("c")) == 0
         assert api.PyDict_DelItem(d, space.wrap("name")) < 0
         assert api.PyErr_Occurred() is space.w_KeyError


--- a/pypy/module/cpyext/test/test_floatobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_floatobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -1,4 +1,5 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 
 class TestFloatObject(BaseApiTest):
     def test_floatobject(self, space, api):
@@ -11,9 +12,24 @@
 
     def test_coerce(self, space, api):
         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))
+
+class AppTestFloatObject(AppTestCpythonExtensionBase):
+    def test_fromstring(self):
+        module = self.import_extension('foo', [
+            ("from_string", "METH_NOARGS",
+             """
+                 PyObject* str = PyString_FromString("1234.56");
+                 PyObject* res = PyFloat_FromString(str, NULL);
+                 Py_DECREF(str);
+                 return res;
+             """),
+            ])
+        assert module.from_string() == 1234.56
+        assert type(module.from_string()) is float


--- a/pypy/module/cpyext/test/test_funcobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_funcobject.py	Sat Dec 18 13:29:01 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_intobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_intobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -1,4 +1,5 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 import sys
 
 class TestIntObject(BaseApiTest):
@@ -28,8 +29,24 @@
         assert api.PyErr_Occurred() is space.w_ValueError
         api.PyErr_Clear()
 
+        assert (api.PyInt_AsUnsignedLongMask(space.wrap(sys.maxint))
+                == sys.maxint)
+        assert (api.PyInt_AsUnsignedLongMask(space.wrap(10**30))
+                == 10**30 % ((sys.maxint + 1) * 2))
+
     def test_coerce(self, space, api):
         class Coerce(object):
             def __int__(self):
                 return 42
         assert api.PyInt_AsLong(space.wrap(Coerce())) == 42
+
+class AppTestIntObject(AppTestCpythonExtensionBase):
+    def test_fromstring(self):
+        module = self.import_extension('foo', [
+            ("from_string", "METH_NOARGS",
+             """
+                 return PyInt_FromString("1234", NULL, 16);
+             """),
+            ])
+        assert module.from_string() == 0x1234
+        assert type(module.from_string()) is int


--- a/pypy/module/cpyext/test/test_longobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_longobject.py	Sat Dec 18 13:29:01 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
@@ -64,11 +64,55 @@
         assert api.PyErr_Occurred()
         api.PyErr_Clear()
 
+        assert api.PyLong_AsUnsignedLongLongMask(
+            space.wrap(1<<64)) == 0
+
+    def test_as_long_and_overflow(self, space, api):
+        overflow = lltype.malloc(rffi.CArrayPtr(rffi.INT_real).TO, 1, flavor='raw')
+        assert api.PyLong_AsLongAndOverflow(
+            space.wrap(sys.maxint), overflow) == sys.maxint
+        assert api.PyLong_AsLongAndOverflow(
+            space.wrap(-sys.maxint - 2), overflow) == -1
+        assert not api.PyErr_Occurred()
+        assert overflow[0] == -1
+        lltype.free(overflow, flavor='raw')
+
+    def test_as_longlong_and_overflow(self, space, api):
+        overflow = lltype.malloc(rffi.CArrayPtr(rffi.INT_real).TO, 1, flavor='raw')
+        assert api.PyLong_AsLongLongAndOverflow(
+            space.wrap(1<<62), overflow) == 1<<62
+        assert api.PyLong_AsLongLongAndOverflow(
+            space.wrap(1<<63), overflow) == -1
+        assert not api.PyErr_Occurred()
+        assert overflow[0] == 1
+        assert api.PyLong_AsLongLongAndOverflow(
+            space.wrap(-1<<64), overflow) == -1
+        assert not api.PyErr_Occurred()
+        assert overflow[0] == -1
+        lltype.free(overflow, flavor='raw')
+
     def test_as_voidptr(self, space, api):
         w_l = api.PyLong_FromVoidPtr(lltype.nullptr(rffi.VOIDP.TO))
         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	Sat Dec 18 13:29:01 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"


--- a/pypy/module/cpyext/test/test_methodobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/test/test_methodobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -3,7 +3,8 @@
 from pypy.module.cpyext.methodobject import PyMethodDef
 from pypy.module.cpyext.api import ApiFunction
 from pypy.module.cpyext.pyobject import PyObject, make_ref, Py_DecRef
-from pypy.module.cpyext.methodobject import PyDescr_NewMethod
+from pypy.module.cpyext.methodobject import (
+    PyDescr_NewMethod, PyCFunction_typedef)
 from pypy.rpython.lltypesystem import rffi, lltype
 
 class AppTestMethodObject(AppTestCpythonExtensionBase):
@@ -50,6 +51,16 @@
              }
              '''
              ),
+            ('isSameFunction', 'METH_O',
+             '''
+             PyCFunction ptr = PyCFunction_GetFunction(args);
+             if (!ptr) return NULL;
+             if (ptr == foo_getarg_O)
+                 Py_RETURN_TRUE;
+             else
+                 Py_RETURN_FALSE;
+             '''
+             ),
             ])
         assert mod.getarg_O(1) == 1
         raises(TypeError, mod.getarg_O)
@@ -64,6 +75,8 @@
         assert mod.getarg_OLD(1, 2) == (1, 2)
 
         assert mod.isCFunction(mod.getarg_O) == "getarg_O"
+        assert mod.isSameFunction(mod.getarg_O)
+        raises(TypeError, mod.isSameFunction, 1)
 
 class TestPyCMethodObject(BaseApiTest):
     def test_repr(self, space):
@@ -78,7 +91,8 @@
         ml = lltype.malloc(PyMethodDef, flavor='raw', zero=True)
         namebuf = rffi.str2charp('func')
         ml.c_ml_name = namebuf
-        ml.c_ml_meth = c_func.get_llhelper(space)
+        ml.c_ml_meth = rffi.cast(PyCFunction_typedef,
+                                 c_func.get_llhelper(space))
 
         method = PyDescr_NewMethod(space, space.w_str, ml)
         assert repr(method).startswith(




--- a/pypy/module/cpyext/typeobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/typeobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -16,10 +16,10 @@
     track_reference, RefcountState, borrow_from)
 from pypy.interpreter.module import Module
 from pypy.module.cpyext import structmemberdefs
-from pypy.module.cpyext.modsupport import convert_method_defs, PyCFunction
+from pypy.module.cpyext.modsupport import convert_method_defs
 from pypy.module.cpyext.state import State
 from pypy.module.cpyext.methodobject import (
-    PyDescr_NewWrapper, PyCFunction_NewEx)
+    PyDescr_NewWrapper, PyCFunction_NewEx, PyCFunction_typedef)
 from pypy.module.cpyext.pyobject import Py_IncRef, Py_DecRef, _Py_Dealloc
 from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
 from pypy.module.cpyext.typeobjectdefs import (
@@ -208,7 +208,7 @@
 
 def setup_new_method_def(space):
     ptr = get_new_method_def(space)
-    ptr.c_ml_meth = rffi.cast(PyCFunction,
+    ptr.c_ml_meth = rffi.cast(PyCFunction_typedef,
         llhelper(tp_new_wrapper.api_func.functype,
                  tp_new_wrapper.api_func.get_wrapper(space)))
 


--- a/pypy/module/cpyext/typeobjectdefs.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/typeobjectdefs.py	Sat Dec 18 13:29:01 2010 +0100
@@ -8,7 +8,6 @@
 from pypy.module.cpyext.modsupport import PyMethodDef
 
 
-PyCFunction = Ptr(FuncType([PyObject, PyObject], PyObject))
 P, FT, PyO = Ptr, FuncType, PyObject
 PyOPtr = Ptr(lltype.Array(PyO, hints={'nolength': True}))
 


--- a/pypy/module/cpyext/unicodeobject.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/module/cpyext/unicodeobject.py	Sat Dec 18 13:29:01 2010 +0100
@@ -122,7 +122,7 @@
         ref_unicode.c_buffer = rffi.unicode2wcharp(u)
     return ref_unicode.c_buffer
 
- at cpython_api([PyObject], rffi.CWCHARP, error=lltype.nullptr(rffi.CWCHARP.TO))
+ at cpython_api([PyObject], rffi.CWCHARP)
 def PyUnicode_AsUnicode(space, ref):
     """Return a read-only pointer to the Unicode object's internal Py_UNICODE
     buffer, NULL if unicode is not a Unicode object."""
@@ -253,6 +253,15 @@
         w_errors = space.w_None
     return space.call_method(w_str, 'decode', w_encoding, w_errors)
 
+ at cpython_api([PyObject], PyObject)
+def PyUnicode_FromObject(space, w_obj):
+    """Shortcut for PyUnicode_FromEncodedObject(obj, NULL, "strict") which is used
+    throughout the interpreter whenever coercion to Unicode is needed."""
+    if space.is_w(space.type(w_obj), space.w_unicode):
+        return w_obj
+    else:
+        return space.call_function(space.w_unicode, w_obj)
+
 @cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
 def PyUnicode_FromEncodedObject(space, w_obj, encoding, errors):
     """Coerce an encoded object obj to an Unicode object and return a reference with
@@ -287,6 +296,25 @@
                              space.wrap("decoding Unicode is not supported"))
     return space.call_function(w_meth, w_encoding, w_errors)
 
+ at cpython_api([CONST_STRING], PyObject)
+def PyUnicode_FromString(space, s):
+    """Create a Unicode object from an UTF-8 encoded null-terminated char buffer"""
+    w_str = space.wrap(rffi.charp2str(s))
+    return space.call_method(w_str, 'decode', space.wrap("utf-8"))
+
+ at cpython_api([CONST_STRING, Py_ssize_t], PyObject)
+def PyUnicode_FromStringAndSize(space, s, size):
+    """Create a Unicode Object from the char buffer u. The bytes will be
+    interpreted as being UTF-8 encoded. u may also be NULL which causes the
+    contents to be undefined. It is the user's responsibility to fill in the
+    needed data. The buffer is copied into the new object. If the buffer is not
+    NULL, the return value might be a shared object. Therefore, modification of
+    the resulting Unicode object is only allowed when u is NULL."""
+    if not s:
+        raise NotImplementedError
+    w_str = space.wrap(rffi.charpsize2str(s, size))
+    return space.call_method(w_str, 'decode', space.wrap("utf-8"))
+
 @cpython_api([PyObject], PyObject)
 def PyUnicode_AsUTF8String(space, w_unicode):
     """Encode a Unicode object using UTF-8 and return the result as Python string
@@ -405,3 +433,10 @@
         else:
             w_errors = space.w_None
         return space.call_method(w_str, 'decode', w_encoding, w_errors)
+
+ at cpython_api([PyObject, PyObject], rffi.INT_real, error=-2)
+def PyUnicode_Compare(space, w_left, w_right):
+    """Compare two strings and return -1, 0, 1 for less than, equal, and greater
+    than, respectively."""
+    return space.int_w(space.cmp(w_left, w_right))
+


--- a/pypy/rlib/rdynload.py	Fri Dec 17 15:09:04 2010 +0100
+++ b/pypy/rlib/rdynload.py	Sat Dec 18 13:29:01 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