Author: Amaury Forgeot d'Arc <amaur...@gmail.com>
Branch: py3k
Changeset: r54857:bcf26626c1c6
Date: 2012-04-30 22:49 +0200
http://bitbucket.org/pypy/pypy/changeset/bcf26626c1c6/

Log:    hg merge default

diff --git a/pypy/module/cpyext/complexobject.py 
b/pypy/module/cpyext/complexobject.py
--- a/pypy/module/cpyext/complexobject.py
+++ b/pypy/module/cpyext/complexobject.py
@@ -33,6 +33,11 @@
         # CPython also accepts anything
         return 0.0
 
+@cpython_api([Py_complex_ptr], PyObject)
+def _PyComplex_FromCComplex(space, v):
+    """Create a new Python complex number object from a C Py_complex value."""
+    return space.newcomplex(v.c_real, v.c_imag)
+
 # lltype does not handle functions returning a structure.  This implements a
 # helper function, which takes as argument a reference to the return value.
 @cpython_api([PyObject, Py_complex_ptr], lltype.Void)
diff --git a/pypy/module/cpyext/include/complexobject.h 
b/pypy/module/cpyext/include/complexobject.h
--- a/pypy/module/cpyext/include/complexobject.h
+++ b/pypy/module/cpyext/include/complexobject.h
@@ -21,6 +21,8 @@
     return result;
 }
 
+#define PyComplex_FromCComplex(c) _PyComplex_FromCComplex(&c)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -1,6 +1,7 @@
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.module.cpyext.api import (cpython_api, PyObject, build_type_checkers,
-                                    CONST_STRING, ADDR, CANNOT_FAIL)
+from pypy.module.cpyext.api import (
+    cpython_api, PyObject, build_type_checkers, Py_ssize_t,
+    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
@@ -56,6 +57,14 @@
     and -1 will be returned."""
     return space.int_w(w_long)
 
+@cpython_api([PyObject], Py_ssize_t, error=-1)
+def PyLong_AsSsize_t(space, w_long):
+    """Return a C Py_ssize_t representation of the contents of pylong.  If
+    pylong is greater than PY_SSIZE_T_MAX, an OverflowError is raised
+    and -1 will be returned.
+    """
+    return space.int_w(w_long)
+
 @cpython_api([PyObject], rffi.LONGLONG, error=-1)
 def PyLong_AsLongLong(space, w_long):
     """
diff --git a/pypy/module/cpyext/src/abstract.c 
b/pypy/module/cpyext/src/abstract.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/src/abstract.c
@@ -0,0 +1,269 @@
+/* Abstract Object Interface */
+
+#include "Python.h"
+
+/* Shorthands to return certain errors */
+
+static PyObject *
+type_error(const char *msg, PyObject *obj)
+{
+    PyErr_Format(PyExc_TypeError, msg, obj->ob_type->tp_name);
+    return NULL;
+}
+
+static PyObject *
+null_error(void)
+{
+    if (!PyErr_Occurred())
+        PyErr_SetString(PyExc_SystemError,
+                        "null argument to internal routine");
+    return NULL;
+}
+
+/* Operations on any object */
+
+int
+PyObject_CheckReadBuffer(PyObject *obj)
+{
+    PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
+
+    if (pb == NULL ||
+        pb->bf_getreadbuffer == NULL ||
+        pb->bf_getsegcount == NULL ||
+        (*pb->bf_getsegcount)(obj, NULL) != 1)
+        return 0;
+    return 1;
+}
+
+int PyObject_AsReadBuffer(PyObject *obj,
+                          const void **buffer,
+                          Py_ssize_t *buffer_len)
+{
+    PyBufferProcs *pb;
+    void *pp;
+    Py_ssize_t len;
+
+    if (obj == NULL || buffer == NULL || buffer_len == NULL) {
+        null_error();
+        return -1;
+    }
+    pb = obj->ob_type->tp_as_buffer;
+    if (pb == NULL ||
+         pb->bf_getreadbuffer == NULL ||
+         pb->bf_getsegcount == NULL) {
+        PyErr_SetString(PyExc_TypeError,
+                        "expected a readable buffer object");
+        return -1;
+    }
+    if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "expected a single-segment buffer object");
+        return -1;
+    }
+    len = (*pb->bf_getreadbuffer)(obj, 0, &pp);
+    if (len < 0)
+        return -1;
+    *buffer = pp;
+    *buffer_len = len;
+    return 0;
+}
+
+int PyObject_AsWriteBuffer(PyObject *obj,
+                           void **buffer,
+                           Py_ssize_t *buffer_len)
+{
+    PyBufferProcs *pb;
+    void*pp;
+    Py_ssize_t len;
+
+    if (obj == NULL || buffer == NULL || buffer_len == NULL) {
+        null_error();
+        return -1;
+    }
+    pb = obj->ob_type->tp_as_buffer;
+    if (pb == NULL ||
+         pb->bf_getwritebuffer == NULL ||
+         pb->bf_getsegcount == NULL) {
+        PyErr_SetString(PyExc_TypeError,
+                        "expected a writeable buffer object");
+        return -1;
+    }
+    if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "expected a single-segment buffer object");
+        return -1;
+    }
+    len = (*pb->bf_getwritebuffer)(obj,0,&pp);
+    if (len < 0)
+        return -1;
+    *buffer = pp;
+    *buffer_len = len;
+    return 0;
+}
+
+/* Operations on callable objects */
+
+static PyObject*
+call_function_tail(PyObject *callable, PyObject *args)
+{
+    PyObject *retval;
+
+    if (args == NULL)
+        return NULL;
+
+    if (!PyTuple_Check(args)) {
+        PyObject *a;
+
+        a = PyTuple_New(1);
+        if (a == NULL) {
+            Py_DECREF(args);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(a, 0, args);
+        args = a;
+    }
+    retval = PyObject_Call(callable, args, NULL);
+
+    Py_DECREF(args);
+
+    return retval;
+}
+
+PyObject *
+PyObject_CallFunction(PyObject *callable, const char *format, ...)
+{
+    va_list va;
+    PyObject *args;
+
+    if (callable == NULL)
+        return null_error();
+
+    if (format && *format) {
+        va_start(va, format);
+        args = Py_VaBuildValue(format, va);
+        va_end(va);
+    }
+    else
+        args = PyTuple_New(0);
+
+    return call_function_tail(callable, args);
+}
+
+PyObject *
+PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
+{
+    va_list va;
+    PyObject *args;
+    PyObject *func = NULL;
+    PyObject *retval = NULL;
+
+    if (o == NULL || name == NULL)
+        return null_error();
+
+    func = PyObject_GetAttrString(o, name);
+    if (func == NULL) {
+        PyErr_SetString(PyExc_AttributeError, name);
+        return 0;
+    }
+
+    if (!PyCallable_Check(func)) {
+        type_error("attribute of type '%.200s' is not callable", func);
+        goto exit;
+    }
+
+    if (format && *format) {
+        va_start(va, format);
+        args = Py_VaBuildValue(format, va);
+        va_end(va);
+    }
+    else
+        args = PyTuple_New(0);
+
+    retval = call_function_tail(func, args);
+
+  exit:
+    /* args gets consumed in call_function_tail */
+    Py_XDECREF(func);
+
+    return retval;
+}
+
+static PyObject *
+objargs_mktuple(va_list va)
+{
+    int i, n = 0;
+    va_list countva;
+    PyObject *result, *tmp;
+
+#ifdef VA_LIST_IS_ARRAY
+    memcpy(countva, va, sizeof(va_list));
+#else
+#ifdef __va_copy
+    __va_copy(countva, va);
+#else
+    countva = va;
+#endif
+#endif
+
+    while (((PyObject *)va_arg(countva, PyObject *)) != NULL)
+        ++n;
+    result = PyTuple_New(n);
+    if (result != NULL && n > 0) {
+        for (i = 0; i < n; ++i) {
+            tmp = (PyObject *)va_arg(va, PyObject *);
+            Py_INCREF(tmp);
+            PyTuple_SET_ITEM(result, i, tmp);
+        }
+    }
+    return result;
+}
+
+PyObject *
+PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
+{
+    PyObject *args, *tmp;
+    va_list vargs;
+
+    if (callable == NULL || name == NULL)
+        return null_error();
+
+    callable = PyObject_GetAttr(callable, name);
+    if (callable == NULL)
+        return NULL;
+
+    /* count the args */
+    va_start(vargs, name);
+    args = objargs_mktuple(vargs);
+    va_end(vargs);
+    if (args == NULL) {
+        Py_DECREF(callable);
+        return NULL;
+    }
+    tmp = PyObject_Call(callable, args, NULL);
+    Py_DECREF(args);
+    Py_DECREF(callable);
+
+    return tmp;
+}
+
+PyObject *
+PyObject_CallFunctionObjArgs(PyObject *callable, ...)
+{
+    PyObject *args, *tmp;
+    va_list vargs;
+
+    if (callable == NULL)
+        return null_error();
+
+    /* count the args */
+    va_start(vargs, callable);
+    args = objargs_mktuple(vargs);
+    va_end(vargs);
+    if (args == NULL)
+        return NULL;
+    tmp = PyObject_Call(callable, args, NULL);
+    Py_DECREF(args);
+
+    return tmp;
+}
+
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -1431,14 +1431,6 @@
     changes in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
-@cpython_api([PyObject], Py_ssize_t, error=-1)
-def PyLong_AsSsize_t(space, pylong):
-    """Return a C Py_ssize_t representation of the contents of pylong.  If
-    pylong is greater than PY_SSIZE_T_MAX, an OverflowError is raised
-    and -1 will be returned.
-    """
-    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
diff --git a/pypy/module/cpyext/test/test_complexobject.py 
b/pypy/module/cpyext/test/test_complexobject.py
--- a/pypy/module/cpyext/test/test_complexobject.py
+++ b/pypy/module/cpyext/test/test_complexobject.py
@@ -31,3 +31,12 @@
         assert module.as_tuple(12-34j) == (12, -34)
         assert module.as_tuple(-3.14) == (-3.14, 0.0)
         raises(TypeError, module.as_tuple, "12")
+
+    def test_FromCComplex(self):
+        module = self.import_extension('foo', [
+            ("test", "METH_NOARGS",
+             """
+                 Py_complex c = {1.2, 3.4};
+                 return PyComplex_FromCComplex(c);
+             """)])
+        assert module.test() == 1.2 + 3.4j
diff --git a/pypy/module/cpyext/test/test_longobject.py 
b/pypy/module/cpyext/test/test_longobject.py
--- a/pypy/module/cpyext/test/test_longobject.py
+++ b/pypy/module/cpyext/test/test_longobject.py
@@ -31,6 +31,11 @@
         value = api.PyLong_AsUnsignedLong(w_value)
         assert value == (sys.maxint - 1) * 2
 
+    def test_as_ssize_t(self, space, api):
+        w_value = space.newlong(2)
+        value = api.PyLong_AsSsize_t(w_value)
+        assert value == 2
+
     def test_fromdouble(self, space, api):
         w_value = api.PyLong_FromDouble(-12.74)
         assert space.unwrap(w_value) == -12
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to