Author: Amaury Forgeot d'Arc <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit