[pypy-commit] pypy py3k: cpyext: add support for the new buffer interface.
amauryfa
noreply at buildbot.pypy.org
Fri Sep 21 23:53:36 CEST 2012
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r57468:4cbe89f3cec7
Date: 2012-09-21 23:52 +0200
http://bitbucket.org/pypy/pypy/changeset/4cbe89f3cec7/
Log: cpyext: add support for the new buffer interface. Most of the tests
pass now...
diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -45,7 +45,6 @@
import pypy.module.cpyext.listobject
import pypy.module.cpyext.sequence
import pypy.module.cpyext.buffer
-import pypy.module.cpyext.bufferobject
import pypy.module.cpyext.eval
import pypy.module.cpyext.import_
import pypy.module.cpyext.mapping
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -186,6 +186,9 @@
self.argnames = argnames[1:]
assert len(self.argnames) == len(self.argtypes)
+ def __repr__(self):
+ return "<cpyext function %s>" % (self.callable.__name__,)
+
def _freeze_(self):
return True
@@ -358,8 +361,7 @@
'PyEval_CallFunction', 'PyEval_CallMethod', 'PyObject_CallFunction',
'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
- 'PyBuffer_FromMemory', 'PyBuffer_FromReadWriteMemory', 'PyBuffer_FromObject',
- 'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', 'init_bufferobject',
+ 'PyObject_GetBuffer', 'PyBuffer_Release',
'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr',
'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr',
@@ -633,11 +635,9 @@
globals()['va_get_%s' % name_no_star] = func
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(),
])
@@ -954,7 +954,6 @@
source_dir / "mysnprintf.c",
source_dir / "pythonrun.c",
source_dir / "sysmodule.c",
- source_dir / "bufferobject.c",
source_dir / "cobject.c",
source_dir / "structseq.c",
source_dir / "capsule.c",
diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py
--- a/pypy/module/cpyext/buffer.py
+++ b/pypy/module/cpyext/buffer.py
@@ -4,38 +4,10 @@
cpython_api, CANNOT_FAIL, Py_buffer)
from pypy.module.cpyext.pyobject import PyObject
- at cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
-def PyObject_CheckBuffer(space, w_obj):
- """Return 1 if obj supports the buffer interface otherwise 0."""
- return 0 # the bf_getbuffer field is never filled by cpyext
-
- at cpython_api([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real],
- rffi.INT_real, error=-1)
-def PyObject_GetBuffer(space, w_obj, view, flags):
- """Export obj into a Py_buffer, view. These arguments must
- never be NULL. The flags argument is a bit field indicating what
- kind of buffer the caller is prepared to deal with and therefore what
- kind of buffer the exporter is allowed to return. The buffer interface
- allows for complicated memory sharing possibilities, but some caller may
- not be able to handle all the complexity but may want to see if the
- exporter will let them take a simpler view to its memory.
-
- Some exporters may not be able to share memory in every possible way and
- may need to raise errors to signal to some consumers that something is
- just not possible. These errors should be a BufferError unless
- there is another error that is actually causing the problem. The
- exporter can use flags information to simplify how much of the
- Py_buffer structure is filled in with non-default values and/or
- raise an error if the object can't support a simpler view of its memory.
-
- 0 is returned on success and -1 on error."""
- raise OperationError(space.w_TypeError, space.wrap(
- 'PyPy does not yet implement the new buffer interface'))
-
@cpython_api([lltype.Ptr(Py_buffer), lltype.Char], rffi.INT_real, error=CANNOT_FAIL)
def PyBuffer_IsContiguous(space, view, fortran):
"""Return 1 if the memory defined by the view is C-style (fortran is
'C') or Fortran-style (fortran is 'F') contiguous or either one
(fortran is 'A'). Return 0 otherwise."""
# PyPy only supports contiguous Py_buffers for now.
- return space.wrap(1)
+ return 1
diff --git a/pypy/module/cpyext/bufferobject.py b/pypy/module/cpyext/bufferobject.py
deleted file mode 100644
--- a/pypy/module/cpyext/bufferobject.py
+++ /dev/null
@@ -1,80 +0,0 @@
-from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import (
- cpython_api, Py_ssize_t, cpython_struct, bootstrap_function,
- PyObjectFields, PyObject)
-from pypy.module.cpyext.pyobject import make_typedescr, Py_DecRef, make_ref
-from pypy.interpreter.buffer import Buffer, StringBuffer, SubBuffer
-from pypy.interpreter.error import OperationError
-from pypy.module.array.interp_array import ArrayBuffer
-
-
-PyBufferObjectStruct = lltype.ForwardReference()
-PyBufferObject = lltype.Ptr(PyBufferObjectStruct)
-PyBufferObjectFields = PyObjectFields + (
- ("b_base", PyObject),
- ("b_ptr", rffi.VOIDP),
- ("b_size", Py_ssize_t),
- ("b_offset", Py_ssize_t),
- ("b_readonly", rffi.INT),
- ("b_hash", rffi.LONG),
- )
-
-cpython_struct("PyBufferObject", PyBufferObjectFields, PyBufferObjectStruct)
-
- at bootstrap_function
-def init_bufferobject(space):
- "Type description of PyBufferObject"
- make_typedescr(space.gettypefor(Buffer).instancetypedef,
- basestruct=PyBufferObject.TO,
- attach=buffer_attach,
- dealloc=buffer_dealloc,
- realize=buffer_realize)
-
-def buffer_attach(space, py_obj, w_obj):
- """
- Fills a newly allocated PyBufferObject with the given (str) buffer object.
- """
- py_buf = rffi.cast(PyBufferObject, py_obj)
- py_buf.c_b_offset = 0
- rffi.setintfield(py_buf, 'c_b_readonly', 1)
- rffi.setintfield(py_buf, 'c_b_hash', -1)
-
- if isinstance(w_obj, SubBuffer):
- py_buf.c_b_offset = w_obj.offset
- w_obj = w_obj.buffer
-
- # If w_obj already allocated a fixed buffer, use it, and keep a
- # reference to w_obj.
- # Otherwise, b_base stays NULL, and we own the b_ptr.
-
- if isinstance(w_obj, StringBuffer):
- py_buf.c_b_base = lltype.nullptr(PyObject.TO)
- py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(w_obj.value))
- py_buf.c_b_size = w_obj.getlength()
- elif isinstance(w_obj, ArrayBuffer):
- w_base = w_obj.array
- py_buf.c_b_base = make_ref(space, w_base)
- py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, w_obj.array._charbuf_start())
- py_buf.c_b_size = w_obj.getlength()
- else:
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "buffer flavor not supported"))
-
-
-def buffer_realize(space, py_obj):
- """
- Creates the buffer in the PyPy interpreter from a cpyext representation.
- """
- raise OperationError(space.w_NotImplementedError, space.wrap(
- "Don't know how to realize a buffer"))
-
-
- at cpython_api([PyObject], lltype.Void, external=False)
-def buffer_dealloc(space, py_obj):
- py_buf = rffi.cast(PyBufferObject, py_obj)
- if py_buf.c_b_base:
- Py_DecRef(space, py_buf.c_b_base)
- else:
- rffi.free_charp(rffi.cast(rffi.CCHARP, py_buf.c_b_ptr))
- from pypy.module.cpyext.object import PyObject_dealloc
- PyObject_dealloc(space, py_obj)
diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -83,6 +83,7 @@
#include "pyconfig.h"
#include "object.h"
+#include "abstract.h"
#include "pyport.h"
#include "warnings.h"
@@ -117,7 +118,6 @@
#include "pymem.h"
#include "pycobject.h"
#include "pycapsule.h"
-#include "bufferobject.h"
#include "bytesobject.h"
#include "sliceobject.h"
#include "datetime.h"
diff --git a/pypy/module/cpyext/include/abstract.h b/pypy/module/cpyext/include/abstract.h
--- a/pypy/module/cpyext/include/abstract.h
+++ b/pypy/module/cpyext/include/abstract.h
@@ -1,1 +1,28 @@
-/* empty */
+#ifndef Py_ABSTRACTOBJECT_H
+#define Py_ABSTRACTOBJECT_H
+
+ /* new buffer API */
+
+#define PyObject_CheckBuffer(obj) \
+ (((obj)->ob_type->tp_as_buffer != NULL) && \
+ ((obj)->ob_type->tp_as_buffer->bf_getbuffer != NULL))
+
+ /* Return 1 if the getbuffer function is available, otherwise
+ return 0 */
+
+ PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view,
+ int flags);
+
+ /* This is a C-API version of the getbuffer function call. It checks
+ to make sure object has the required function pointer and issues the
+ call. Returns -1 and raises an error on failure and returns 0 on
+ success
+ */
+
+
+ PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view);
+
+ /* Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
+ */
+
+#endif /* Py_ABSTRACTOBJECT_H */
diff --git a/pypy/module/cpyext/include/bufferobject.h b/pypy/module/cpyext/include/bufferobject.h
deleted file mode 100644
--- a/pypy/module/cpyext/include/bufferobject.h
+++ /dev/null
@@ -1,45 +0,0 @@
-
-/* Buffer object interface */
-
-/* Note: the object's structure is private */
-
-#ifndef Py_BUFFEROBJECT_H
-#define Py_BUFFEROBJECT_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- PyObject_HEAD
- PyObject *b_base;
- void *b_ptr;
- Py_ssize_t b_size;
- Py_ssize_t b_offset;
- int b_readonly;
- long b_hash;
-} PyBufferObject;
-
-
-PyAPI_DATA(PyTypeObject) PyBuffer_Type;
-
-#define PyBuffer_Check(op) (((PyObject*)(op))->ob_type == &PyBuffer_Type)
-
-#define Py_END_OF_BUFFER (-1)
-
-PyObject* PyBuffer_FromObject(PyObject *base,
- Py_ssize_t offset, Py_ssize_t size);
-PyObject* PyBuffer_FromReadWriteObject(PyObject *base,
- Py_ssize_t offset,
- Py_ssize_t size);
-
-PyObject* PyBuffer_FromMemory(void *ptr, Py_ssize_t size);
-PyObject* PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size);
-
-PyObject* PyBuffer_New(Py_ssize_t size);
-
-void init_bufferobject(void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* !Py_BUFFEROBJECT_H */
diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -125,17 +125,6 @@
typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *);
-/* int-based buffer interface */
-typedef int (*getreadbufferproc)(PyObject *, int, void **);
-typedef int (*getwritebufferproc)(PyObject *, int, void **);
-typedef int (*getsegcountproc)(PyObject *, int *);
-typedef int (*getcharbufferproc)(PyObject *, int, char **);
-/* ssize_t-based buffer interface */
-typedef Py_ssize_t (*readbufferproc)(PyObject *, Py_ssize_t, void **);
-typedef Py_ssize_t (*writebufferproc)(PyObject *, Py_ssize_t, void **);
-typedef Py_ssize_t (*segcountproc)(PyObject *, Py_ssize_t *);
-typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **);
-
/* Py3k buffer interface */
typedef struct bufferinfo {
void *buf;
@@ -274,12 +263,8 @@
} PyMappingMethods;
typedef struct {
- readbufferproc bf_getreadbuffer;
- writebufferproc bf_getwritebuffer;
- segcountproc bf_getsegcount;
- charbufferproc bf_getcharbuffer;
- getbufferproc bf_getbuffer;
- releasebufferproc bf_releasebuffer;
+ getbufferproc bf_getbuffer;
+ releasebufferproc bf_releasebuffer;
} PyBufferProcs;
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -471,15 +471,3 @@
view.c_internal = lltype.nullptr(rffi.VOIDP.TO)
return 0
-
-
- at cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL)
-def PyBuffer_Release(space, view):
- """
- Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
-
- This is not a complete re-implementation of the CPython API; it only
- provides a subset of CPython's behavior.
- """
- Py_DecRef(space, view.c_obj)
- view.c_obj = lltype.nullptr(PyObject.TO)
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -4,13 +4,13 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
- cpython_api, generic_cpy_call, PyObject, Py_ssize_t)
+ cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_buffer)
from pypy.module.cpyext.typeobjectdefs import (
unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
- readbufferproc)
+ getbufferproc, releasebufferproc)
from pypy.module.cpyext.pyobject import from_ref
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
@@ -242,14 +242,15 @@
def getitem(self, index):
return self.ptr[index]
-def wrap_getreadbuffer(space, w_self, w_args, func):
- func_target = rffi.cast(readbufferproc, func)
- with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr:
- index = rffi.cast(Py_ssize_t, 0)
- size = generic_cpy_call(space, func_target, w_self, index, ptr)
- if size < 0:
+def wrap_getbuffer(space, w_self, w_args, func):
+ func_target = rffi.cast(getbufferproc, func)
+ with lltype.scoped_alloc(Py_buffer) as view:
+ flags = rffi.cast(rffi.INT_real, 0)
+ print "AFA CALL GETBUFFER"
+ ret = generic_cpy_call(space, func_target, w_self, view, flags)
+ if ret < 0:
space.fromcache(State).check_and_raise_exception(always=True)
- return space.wrap(CPyBuffer(ptr[0], size, w_self))
+ return space.wrap(CPyBuffer(view.c_buf, view.c_len, w_self))
def get_richcmp_func(OP_CONST):
def inner(space, w_self, w_args, func):
@@ -643,7 +644,7 @@
slotdefs = eval(slotdefs_str)
# PyPy addition
slotdefs += (
- TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
+ TPSLOT("__buffer__", "tp_as_buffer.c_bf_getbuffer", None, "wrap_getbuffer", ""),
)
# partial sort to solve some slot conflicts:
diff --git a/pypy/module/cpyext/src/abstract.c b/pypy/module/cpyext/src/abstract.c
--- a/pypy/module/cpyext/src/abstract.c
+++ b/pypy/module/cpyext/src/abstract.c
@@ -26,12 +26,16 @@
PyObject_CheckReadBuffer(PyObject *obj)
{
PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
+ Py_buffer view;
if (pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL ||
- (*pb->bf_getsegcount)(obj, NULL) != 1)
+ pb->bf_getbuffer == NULL)
return 0;
+ if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE) == -1) {
+ PyErr_Clear();
+ return 0;
+ }
+ PyBuffer_Release(&view);
return 1;
}
@@ -40,8 +44,7 @@
Py_ssize_t *buffer_len)
{
PyBufferProcs *pb;
- void *pp;
- Py_ssize_t len;
+ Py_buffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
@@ -49,22 +52,19 @@
}
pb = obj->ob_type->tp_as_buffer;
if (pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL) {
+ pb->bf_getbuffer == NULL) {
PyErr_SetString(PyExc_TypeError,
- "expected a readable buffer object");
+ "expected an object with a buffer interface");
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;
+
+ if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE)) return -1;
+
+ *buffer = view.buf;
+ *buffer_len = view.len;
+ if (pb->bf_releasebuffer != NULL)
+ (*pb->bf_releasebuffer)(obj, &view);
+ Py_XDECREF(view.obj);
return 0;
}
@@ -73,8 +73,7 @@
Py_ssize_t *buffer_len)
{
PyBufferProcs *pb;
- void*pp;
- Py_ssize_t len;
+ Py_buffer view;
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
null_error();
@@ -82,23 +81,43 @@
}
pb = obj->ob_type->tp_as_buffer;
if (pb == NULL ||
- pb->bf_getwritebuffer == NULL ||
- pb->bf_getsegcount == NULL) {
+ pb->bf_getbuffer == NULL ||
+ ((*pb->bf_getbuffer)(obj, &view, PyBUF_WRITABLE) != 0)) {
PyErr_SetString(PyExc_TypeError,
- "expected a writeable buffer object");
+ "expected an object with a writable buffer interface");
return -1;
}
- if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
+
+ *buffer = view.buf;
+ *buffer_len = view.len;
+ if (pb->bf_releasebuffer != NULL)
+ (*pb->bf_releasebuffer)(obj, &view);
+ Py_XDECREF(view.obj);
+ return 0;
+}
+
+/* Buffer C-API for Python 3.0 */
+
+int
+PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
+{
+ if (!PyObject_CheckBuffer(obj)) {
+ PyErr_Format(PyExc_TypeError,
+ "'%100s' does not support the buffer interface",
+ Py_TYPE(obj)->tp_name);
return -1;
}
- len = (*pb->bf_getwritebuffer)(obj,0,&pp);
- if (len < 0)
- return -1;
- *buffer = pp;
- *buffer_len = len;
- return 0;
+ return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
+}
+
+void
+PyBuffer_Release(Py_buffer *view)
+{
+ PyObject *obj = view->obj;
+ if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer)
+ Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view);
+ Py_XDECREF(obj);
+ view->obj = NULL;
}
/* Operations on callable objects */
diff --git a/pypy/module/cpyext/src/bufferobject.c b/pypy/module/cpyext/src/bufferobject.c
deleted file mode 100644
--- a/pypy/module/cpyext/src/bufferobject.c
+++ /dev/null
@@ -1,853 +0,0 @@
-
-/* Buffer object implementation */
-
-#include "Python.h"
-
-
-enum buffer_t {
- READ_BUFFER,
- WRITE_BUFFER,
- CHAR_BUFFER,
- ANY_BUFFER
-};
-
-static int
-get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
- enum buffer_t buffer_type)
-{
- if (self->b_base == NULL) {
- assert (ptr != NULL);
- *ptr = self->b_ptr;
- *size = self->b_size;
- }
- else {
- Py_ssize_t count, offset;
- readbufferproc proc = 0;
- PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
- if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return 0;
- }
- if ((buffer_type == READ_BUFFER) ||
- ((buffer_type == ANY_BUFFER) && self->b_readonly))
- proc = bp->bf_getreadbuffer;
- else if ((buffer_type == WRITE_BUFFER) ||
- (buffer_type == ANY_BUFFER))
- proc = (readbufferproc)bp->bf_getwritebuffer;
- else if (buffer_type == CHAR_BUFFER) {
- if (!PyType_HasFeature(self->ob_type,
- Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
- PyErr_SetString(PyExc_TypeError,
- "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
- return 0;
- }
- proc = (readbufferproc)bp->bf_getcharbuffer;
- }
- if (!proc) {
- char *buffer_type_name;
- switch (buffer_type) {
- case READ_BUFFER:
- buffer_type_name = "read";
- break;
- case WRITE_BUFFER:
- buffer_type_name = "write";
- break;
- case CHAR_BUFFER:
- buffer_type_name = "char";
- break;
- default:
- buffer_type_name = "no";
- break;
- }
- PyErr_Format(PyExc_TypeError,
- "%s buffer type not available",
- buffer_type_name);
- return 0;
- }
- if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
- return 0;
- /* apply constraints to the start/end */
- if (self->b_offset > count)
- offset = count;
- else
- offset = self->b_offset;
- *(char **)ptr = *(char **)ptr + offset;
- if (self->b_size == Py_END_OF_BUFFER)
- *size = count;
- else
- *size = self->b_size;
- if (offset + *size > count)
- *size = count - offset;
- }
- return 1;
-}
-
-
-static PyObject *
-buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
- int readonly)
-{
- PyBufferObject * b;
-
- if (size < 0 && size != Py_END_OF_BUFFER) {
- PyErr_SetString(PyExc_ValueError,
- "size must be zero or positive");
- return NULL;
- }
- if (offset < 0) {
- PyErr_SetString(PyExc_ValueError,
- "offset must be zero or positive");
- return NULL;
- }
-
- b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
- if ( b == NULL )
- return NULL;
-
- Py_XINCREF(base);
- b->b_base = base;
- b->b_ptr = ptr;
- b->b_size = size;
- b->b_offset = offset;
- b->b_readonly = readonly;
- b->b_hash = -1;
-
- return (PyObject *) b;
-}
-
-static PyObject *
-buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
-{
- if (offset < 0) {
- PyErr_SetString(PyExc_ValueError,
- "offset must be zero or positive");
- return NULL;
- }
- if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
- /* another buffer, refer to the base object */
- PyBufferObject *b = (PyBufferObject *)base;
- if (b->b_size != Py_END_OF_BUFFER) {
- Py_ssize_t base_size = b->b_size - offset;
- if (base_size < 0)
- base_size = 0;
- if (size == Py_END_OF_BUFFER || size > base_size)
- size = base_size;
- }
- offset += b->b_offset;
- base = b->b_base;
- }
- return buffer_from_memory(base, size, offset, NULL, readonly);
-}
-
-
-PyObject *
-PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
-{
- PyBufferProcs *pb = base->ob_type->tp_as_buffer;
-
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_SetString(PyExc_TypeError, "buffer object expected");
- return NULL;
- }
-
- return buffer_from_object(base, size, offset, 1);
-}
-
-PyObject *
-PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
-{
- PyBufferProcs *pb = base->ob_type->tp_as_buffer;
-
- if ( pb == NULL ||
- pb->bf_getwritebuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_SetString(PyExc_TypeError, "buffer object expected");
- return NULL;
- }
-
- return buffer_from_object(base, size, offset, 0);
-}
-
-PyObject *
-PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
-{
- return buffer_from_memory(NULL, size, 0, ptr, 1);
-}
-
-PyObject *
-PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
-{
- return buffer_from_memory(NULL, size, 0, ptr, 0);
-}
-
-PyObject *
-PyBuffer_New(Py_ssize_t size)
-{
- PyObject *o;
- PyBufferObject * b;
-
- if (size < 0) {
- PyErr_SetString(PyExc_ValueError,
- "size must be zero or positive");
- return NULL;
- }
- if (sizeof(*b) > PY_SSIZE_T_MAX - size) {
- /* unlikely */
- return PyErr_NoMemory();
- }
- /* Inline PyObject_New */
- o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
- if ( o == NULL )
- return PyErr_NoMemory();
- b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
-
- b->b_base = NULL;
- b->b_ptr = (void *)(b + 1);
- b->b_size = size;
- b->b_offset = 0;
- b->b_readonly = 0;
- b->b_hash = -1;
-
- return o;
-}
-
-/* Methods */
-
-static PyObject *
-buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
-{
- PyObject *ob;
- Py_ssize_t offset = 0;
- Py_ssize_t size = Py_END_OF_BUFFER;
-
- /*
- * if (PyErr_WarnPy3k("buffer() not supported in 3.x", 1) < 0)
- * return NULL;
- */
-
- if (!_PyArg_NoKeywords("buffer()", kw))
- return NULL;
-
- if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
- return NULL;
- return PyBuffer_FromObject(ob, offset, size);
-}
-
-PyDoc_STRVAR(buffer_doc,
-"buffer(object [, offset[, size]])\n\
-\n\
-Create a new buffer object which references the given object.\n\
-The buffer will reference a slice of the target object from the\n\
-start of the object (or at the specified offset). The slice will\n\
-extend to the end of the target object (or with the specified size).");
-
-
-static void
-buffer_dealloc(PyBufferObject *self)
-{
- Py_XDECREF(self->b_base);
- PyObject_DEL(self);
-}
-
-static int
-buffer_compare(PyBufferObject *self, PyBufferObject *other)
-{
- void *p1, *p2;
- Py_ssize_t len_self, len_other, min_len;
- int cmp;
-
- if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
- return -1;
- if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
- return -1;
- min_len = (len_self < len_other) ? len_self : len_other;
- if (min_len > 0) {
- cmp = memcmp(p1, p2, min_len);
- if (cmp != 0)
- return cmp < 0 ? -1 : 1;
- }
- return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
-}
-
-static PyObject *
-buffer_repr(PyBufferObject *self)
-{
- const char *status = self->b_readonly ? "read-only" : "read-write";
-
- if ( self->b_base == NULL )
- return PyUnicode_FromFormat("<%s buffer ptr %p, size %zd at %p>",
- status,
- self->b_ptr,
- self->b_size,
- self);
- else
- return PyUnicode_FromFormat(
- "<%s buffer for %p, size %zd, offset %zd at %p>",
- status,
- self->b_base,
- self->b_size,
- self->b_offset,
- self);
-}
-
-static long
-buffer_hash(PyBufferObject *self)
-{
- void *ptr;
- Py_ssize_t size;
- register Py_ssize_t len;
- register unsigned char *p;
- register long x;
-
- if ( self->b_hash != -1 )
- return self->b_hash;
-
- /* XXX potential bugs here, a readonly buffer does not imply that the
- * underlying memory is immutable. b_readonly is a necessary but not
- * sufficient condition for a buffer to be hashable. Perhaps it would
- * be better to only allow hashing if the underlying object is known to
- * be immutable (e.g. PyString_Check() is true). Another idea would
- * be to call tp_hash on the underlying object and see if it raises
- * an error. */
- if ( !self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError,
- "writable buffers are not hashable");
- return -1;
- }
-
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return -1;
- p = (unsigned char *) ptr;
- len = size;
- x = *p << 7;
- while (--len >= 0)
- x = (1000003*x) ^ *p++;
- x ^= size;
- if (x == -1)
- x = -2;
- self->b_hash = x;
- return x;
-}
-
-static PyObject *
-buffer_str(PyBufferObject *self)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- return PyString_FromStringAndSize((const char *)ptr, size);
-}
-
-/* Sequence methods */
-
-static Py_ssize_t
-buffer_length(PyBufferObject *self)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return -1;
- return size;
-}
-
-static PyObject *
-buffer_concat(PyBufferObject *self, PyObject *other)
-{
- PyBufferProcs *pb = other->ob_type->tp_as_buffer;
- void *ptr1, *ptr2;
- char *p;
- PyObject *ob;
- Py_ssize_t size, count;
-
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return NULL;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return NULL;
- }
-
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return NULL;
-
- /* optimize special case */
- if ( size == 0 )
- {
- Py_INCREF(other);
- return other;
- }
-
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return NULL;
-
- assert(count <= PY_SIZE_MAX - size);
-
- ob = PyString_FromStringAndSize(NULL, size + count);
- if ( ob == NULL )
- return NULL;
- p = PyString_AS_STRING(ob);
- memcpy(p, ptr1, size);
- memcpy(p + size, ptr2, count);
-
- /* there is an extra byte in the string object, so this is safe */
- p[size + count] = '\0';
-
- return ob;
-}
-
-static PyObject *
-buffer_repeat(PyBufferObject *self, Py_ssize_t count)
-{
- PyObject *ob;
- register char *p;
- void *ptr;
- Py_ssize_t size;
-
- if ( count < 0 )
- count = 0;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- if (count > PY_SSIZE_T_MAX / size) {
- PyErr_SetString(PyExc_MemoryError, "result too large");
- return NULL;
- }
- ob = PyString_FromStringAndSize(NULL, size * count);
- if ( ob == NULL )
- return NULL;
-
- p = PyString_AS_STRING(ob);
- while ( count-- )
- {
- memcpy(p, ptr, size);
- p += size;
- }
-
- /* there is an extra byte in the string object, so this is safe */
- *p = '\0';
-
- return ob;
-}
-
-static PyObject *
-buffer_item(PyBufferObject *self, Py_ssize_t idx)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- if ( idx < 0 || idx >= size ) {
- PyErr_SetString(PyExc_IndexError, "buffer index out of range");
- return NULL;
- }
- return PyString_FromStringAndSize((char *)ptr + idx, 1);
-}
-
-static PyObject *
-buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- if ( left < 0 )
- left = 0;
- if ( right < 0 )
- right = 0;
- if ( right > size )
- right = size;
- if ( right < left )
- right = left;
- return PyString_FromStringAndSize((char *)ptr + left,
- right - left);
-}
-
-static PyObject *
-buffer_subscript(PyBufferObject *self, PyObject *item)
-{
- void *p;
- Py_ssize_t size;
-
- if (!get_buf(self, &p, &size, ANY_BUFFER))
- return NULL;
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += size;
- return buffer_item(self, i);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength, cur, i;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, size,
- &start, &stop, &step, &slicelength) < 0) {
- return NULL;
- }
-
- if (slicelength <= 0)
- return PyString_FromStringAndSize("", 0);
- else if (step == 1)
- return PyString_FromStringAndSize((char *)p + start,
- stop - start);
- else {
- PyObject *result;
- char *source_buf = (char *)p;
- char *result_buf = (char *)PyMem_Malloc(slicelength);
-
- if (result_buf == NULL)
- return PyErr_NoMemory();
-
- for (cur = start, i = 0; i < slicelength;
- cur += step, i++) {
- result_buf[i] = source_buf[cur];
- }
-
- result = PyString_FromStringAndSize(result_buf,
- slicelength);
- PyMem_Free(result_buf);
- return result;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "sequence index must be integer");
- return NULL;
- }
-}
-
-static int
-buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
-{
- PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
- Py_ssize_t count;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
-
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return -1;
-
- if (idx < 0 || idx >= size) {
- PyErr_SetString(PyExc_IndexError,
- "buffer assignment index out of range");
- return -1;
- }
-
- pb = other ? other->ob_type->tp_as_buffer : NULL;
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return -1;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
-
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
- if ( count != 1 ) {
- PyErr_SetString(PyExc_TypeError,
- "right operand must be a single byte");
- return -1;
- }
-
- ((char *)ptr1)[idx] = *(char *)ptr2;
- return 0;
-}
-
-static int
-buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
-{
- PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
- Py_ssize_t slice_len;
- Py_ssize_t count;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
-
- pb = other ? other->ob_type->tp_as_buffer : NULL;
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return -1;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return -1;
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
-
- if ( left < 0 )
- left = 0;
- else if ( left > size )
- left = size;
- if ( right < left )
- right = left;
- else if ( right > size )
- right = size;
- slice_len = right - left;
-
- if ( count != slice_len ) {
- PyErr_SetString(
- PyExc_TypeError,
- "right operand length must match slice length");
- return -1;
- }
-
- if ( slice_len )
- memcpy((char *)ptr1 + left, ptr2, slice_len);
-
- return 0;
-}
-
-static int
-buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
-{
- PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t selfsize;
- Py_ssize_t othersize;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
-
- pb = value ? value->ob_type->tp_as_buffer : NULL;
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return -1;
- }
- if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
- if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
- return -1;
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return -1;
- if (i < 0)
- i += selfsize;
- return buffer_ass_item(self, i, value);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
- &start, &stop, &step, &slicelength) < 0)
- return -1;
-
- if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
- return -1;
-
- if (othersize != slicelength) {
- PyErr_SetString(
- PyExc_TypeError,
- "right operand length must match slice length");
- return -1;
- }
-
- if (slicelength == 0)
- return 0;
- else if (step == 1) {
- memcpy((char *)ptr1 + start, ptr2, slicelength);
- return 0;
- }
- else {
- Py_ssize_t cur, i;
-
- for (cur = start, i = 0; i < slicelength;
- cur += step, i++) {
- ((char *)ptr1)[cur] = ((char *)ptr2)[i];
- }
-
- return 0;
- }
- } else {
- PyErr_SetString(PyExc_TypeError,
- "buffer indices must be integers");
- return -1;
- }
-}
-
-/* Buffer methods */
-
-static Py_ssize_t
-buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
-{
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, pp, &size, READ_BUFFER))
- return -1;
- return size;
-}
-
-static Py_ssize_t
-buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
-{
- Py_ssize_t size;
-
- if ( self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError, "buffer is read-only");
- return -1;
- }
-
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, pp, &size, WRITE_BUFFER))
- return -1;
- return size;
-}
-
-static Py_ssize_t
-buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return -1;
- if (lenp)
- *lenp = size;
- return 1;
-}
-
-static Py_ssize_t
-buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
-{
- void *ptr;
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
- return -1;
- *pp = (const char *)ptr;
- return size;
-}
-
-void init_bufferobject(void)
-{
- PyType_Ready(&PyBuffer_Type);
-}
-
-static PySequenceMethods buffer_as_sequence = {
- (lenfunc)buffer_length, /*sq_length*/
- (binaryfunc)buffer_concat, /*sq_concat*/
- (ssizeargfunc)buffer_repeat, /*sq_repeat*/
- (ssizeargfunc)buffer_item, /*sq_item*/
- (ssizessizeargfunc)buffer_slice, /*sq_slice*/
- (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
- (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
-};
-
-static PyMappingMethods buffer_as_mapping = {
- (lenfunc)buffer_length,
- (binaryfunc)buffer_subscript,
- (objobjargproc)buffer_ass_subscript,
-};
-
-static PyBufferProcs buffer_as_buffer = {
- (readbufferproc)buffer_getreadbuf,
- (writebufferproc)buffer_getwritebuf,
- (segcountproc)buffer_getsegcount,
- (charbufferproc)buffer_getcharbuf,
-};
-
-PyTypeObject PyBuffer_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "buffer",
- sizeof(PyBufferObject),
- 0,
- (destructor)buffer_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)buffer_compare, /* tp_compare */
- (reprfunc)buffer_repr, /* tp_repr */
- 0, /* tp_as_number */
- &buffer_as_sequence, /* tp_as_sequence */
- &buffer_as_mapping, /* tp_as_mapping */
- (hashfunc)buffer_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)buffer_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- &buffer_as_buffer, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
- buffer_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- buffer_new, /* tp_new */
-};
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -1484,7 +1484,7 @@
\n\
Extends this array with data from the unicode string ustr.\n\
The array must be a unicode type array; otherwise a ValueError\n\
-is raised. Use array.frombytes(ustr.decode(...)) to\n\
+is raised. Use array.frombytes(ustr.encode(...)) to\n\
append Unicode data to an array of some other type.");
@@ -1506,7 +1506,7 @@
\n\
Convert the array to a unicode string. The array must be\n\
a unicode type array; otherwise a ValueError is raised. Use\n\
-array.tostring().decode() to obtain a unicode string from\n\
+array.tobytes().decode() to obtain a unicode string from\n\
an array of some other type.");
@@ -2543,7 +2543,7 @@
\n\
Return a new array whose items are restricted by typecode, and\n\
initialized from the optional initializer value, which must be a list,\n\
-string. or iterable over elements of the appropriate type.\n\
+string or iterable over elements of the appropriate type.\n\
\n\
Arrays represent basic values and behave very much like lists, except\n\
the type of objects stored in them is constrained.\n\
@@ -2557,7 +2557,7 @@
extend() -- extend array by appending multiple elements from an iterable\n\
fromfile() -- read items from a file object\n\
fromlist() -- append items from the list\n\
-fromstring() -- append items from the string\n\
+frombytes() -- append items from the string\n\
index() -- return index of first occurrence of an object\n\
insert() -- insert a new item into the array at a provided position\n\
pop() -- remove and return item (default last)\n\
@@ -2565,7 +2565,7 @@
reverse() -- reverse the order of the items in the array\n\
tofile() -- write all items to a file object\n\
tolist() -- return the array converted to an ordinary list\n\
-tostring() -- return the array converted to a string\n\
+tobytes() -- return the array converted to a string\n\
\n\
Attributes:\n\
\n\
diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -115,7 +115,7 @@
{
PyObject *format;
- format = PyString_FromString("<Foo>");
+ format = PyUnicode_FromString("<Foo>");
if (format == NULL) return NULL;
return format;
}
@@ -131,11 +131,11 @@
foo_setattro(fooobject *self, PyObject *name, PyObject *value)
{
char *name_str;
- if (!PyString_Check(name)) {
+ if (!PyUnicode_Check(name)) {
PyErr_SetObject(PyExc_AttributeError, name);
return -1;
}
- name_str = PyString_AsString(name);
+ name_str = _PyUnicode_AsString(name);
if (strcmp(name_str, "set_foo") == 0)
{
long v = PyInt_AsLong(value);
diff --git a/pypy/module/cpyext/test/sre.h b/pypy/module/cpyext/test/sre.h
--- a/pypy/module/cpyext/test/sre.h
+++ b/pypy/module/cpyext/test/sre.h
@@ -30,6 +30,8 @@
PyObject* pattern; /* pattern source (or None) */
int flags; /* flags used when compiling pattern source */
PyObject *weakreflist; /* List of weak references */
+ int charsize; /* pattern charsize (or -1) */
+ Py_buffer view;
/* pattern code */
Py_ssize_t codesize;
SRE_CODE code[1];
@@ -79,6 +81,7 @@
char* data_stack;
size_t data_stack_size;
size_t data_stack_base;
+ Py_buffer buffer;
/* current repeat context */
SRE_REPEAT *repeat;
/* hooks */
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -57,8 +57,8 @@
module = self.import_module(name='array')
arr = module.array('i', [1,2,3,4])
# XXX big-endian
- assert str(buffer(arr)) == ('\x01\0\0\0'
- '\x02\0\0\0'
- '\x03\0\0\0'
- '\x04\0\0\0')
+ assert memoryview(arr).tobytes() == (b'\x01\0\0\0'
+ b'\x02\0\0\0'
+ b'\x03\0\0\0'
+ b'\x04\0\0\0')
diff --git a/pypy/module/cpyext/test/test_bufferobject.py b/pypy/module/cpyext/test/test_bufferobject.py
deleted file mode 100644
--- a/pypy/module/cpyext/test/test_bufferobject.py
+++ /dev/null
@@ -1,64 +0,0 @@
-from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-from pypy.module.cpyext.api import PyObject
-from pypy.module.cpyext.pyobject import Py_DecRef
-
-class AppTestBufferObject(AppTestCpythonExtensionBase):
- def test_FromMemory(self):
- module = self.import_extension('foo', [
- ("get_FromMemory", "METH_NOARGS",
- """
- cbuf = malloc(4);
- cbuf[0] = 'a';
- cbuf[1] = 'b';
- cbuf[2] = 'c';
- cbuf[3] = '\\0';
- return PyBuffer_FromMemory(cbuf, 4);
- """),
- ("free_buffer", "METH_NOARGS",
- """
- free(cbuf);
- Py_RETURN_NONE;
- """),
- ("check_ascharbuffer", "METH_O",
- """
- char *ptr;
- Py_ssize_t size;
- if (PyObject_AsCharBuffer(args, &ptr, &size) < 0)
- return NULL;
- return PyString_FromStringAndSize(ptr, size);
- """)
- ], prologue = """
- static char* cbuf = NULL;
- """)
- buf = module.get_FromMemory()
- assert str(buf) == 'abc\0'
-
- assert module.check_ascharbuffer(buf) == 'abc\0'
-
- module.free_buffer()
-
- def test_Buffer_New(self):
- module = self.import_extension('foo', [
- ("buffer_new", "METH_NOARGS",
- """
- return PyBuffer_New(150);
- """),
- ])
- b = module.buffer_new()
- raises(AttributeError, getattr, b, 'x')
-
- def test_array_buffer(self):
- module = self.import_extension('foo', [
- ("roundtrip", "METH_O",
- """
- PyBufferObject *buf = (PyBufferObject *)args;
- return PyString_FromStringAndSize(buf->b_ptr, buf->b_size);
- """),
- ])
- import array
- a = array.array('c', 'text')
- b = buffer(a)
- assert module.roundtrip(b) == 'text'
-
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -508,15 +508,10 @@
"""
module = self.import_module(name='foo', init=init, body=body)
assert module.return_pi() == 3.14
- print "A"
module.drop_pi()
- print "B"
module.drop_pi()
- print "C"
assert module.return_pi() == 3.14
- print "D"
assert module.return_pi() == 3.14
- print "E"
module.drop_pi()
skip("Hmm, how to check for the exception?")
raises(api.InvalidPointerException, module.return_invalid_pointer)
@@ -738,12 +733,12 @@
char* name2 = Py_GetProgramName();
if (name1 != name2)
Py_RETURN_FALSE;
- return PyString_FromString(name1);
+ return PyUnicode_FromString(name1);
'''
),
])
p = mod.get_programname()
- print p
+ print(p)
assert 'py' in p
def test_get_version(self):
@@ -754,12 +749,12 @@
char* name2 = Py_GetVersion();
if (name1 != name2)
Py_RETURN_FALSE;
- return PyString_FromString(name1);
+ return PyUnicode_FromString(name1);
'''
),
])
p = mod.get_version()
- print p
+ print(p)
assert 'PyPy' in p
def test_no_double_imports(self):
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -11,7 +11,7 @@
generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
Py_TPFLAGS_HAVE_GETCHARBUFFER,
- build_type_checkers, PyObjectFields)
+ build_type_checkers, PyObjectFields, Py_buffer)
from pypy.module.cpyext.pyobject import (
PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
track_reference, RefcountState, borrow_from)
@@ -28,7 +28,6 @@
PyNumberMethods, PyMappingMethods, PySequenceMethods, PyBufferProcs)
from pypy.module.cpyext.slotdefs import (
slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
-from pypy.interpreter.buffer import Buffer
from pypy.interpreter.error import OperationError
from pypy.rlib.rstring import rsplit
from pypy.rlib.objectmodel import specialize
@@ -387,72 +386,24 @@
# hopefully this does not clash with the memory model assumed in
# extension modules
- at cpython_api([PyObject, Py_ssize_tP], lltype.Signed, external=False,
- error=CANNOT_FAIL)
-def str_segcount(space, w_obj, ref):
- if ref:
- ref[0] = space.len_w(w_obj)
- return 1
-
- at cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- external=False, error=-1)
-def str_getreadbuffer(space, w_str, segment, ref):
+ at cpython_api([PyObject, lltype.Ptr(Py_buffer), rffi.INT_real], rffi.INT_real,
+ external=False, error=-1)
+def str_getbuffer(space, w_str, view, flags):
from pypy.module.cpyext.stringobject import PyString_AsString
- if segment != 0:
- raise OperationError(space.w_SystemError, space.wrap
- ("accessing non-existent string segment"))
- pyref = make_ref(space, w_str)
- ref[0] = PyString_AsString(space, pyref)
- # Stolen reference: the object has better exist somewhere else
- Py_DecRef(space, pyref)
- return space.len_w(w_str)
-
- at cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
- external=False, error=-1)
-def str_getcharbuffer(space, w_str, segment, ref):
- from pypy.module.cpyext.stringobject import PyString_AsString
- if segment != 0:
- raise OperationError(space.w_SystemError, space.wrap
- ("accessing non-existent string segment"))
- pyref = make_ref(space, w_str)
- ref[0] = PyString_AsString(space, pyref)
- # Stolen reference: the object has better exist somewhere else
- Py_DecRef(space, pyref)
- return space.len_w(w_str)
-
- at cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
- external=False, error=-1)
-def buf_getreadbuffer(space, pyref, segment, ref):
- from pypy.module.cpyext.bufferobject import PyBufferObject
- if segment != 0:
- raise OperationError(space.w_SystemError, space.wrap
- ("accessing non-existent string segment"))
- py_buf = rffi.cast(PyBufferObject, pyref)
- ref[0] = py_buf.c_b_ptr
- #Py_DecRef(space, pyref)
- return py_buf.c_b_size
+ view.c_obj = make_ref(space, w_str)
+ view.c_buf = rffi.cast(rffi.VOIDP, PyString_AsString(space, view.c_obj))
+ view.c_len = space.len_w(w_str)
+ return 0
def setup_string_buffer_procs(space, pto):
c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
lltype.render_immortal(c_buf)
- c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype,
- str_segcount.api_func.get_wrapper(space))
- c_buf.c_bf_getreadbuffer = llhelper(str_getreadbuffer.api_func.functype,
- str_getreadbuffer.api_func.get_wrapper(space))
- c_buf.c_bf_getcharbuffer = llhelper(str_getcharbuffer.api_func.functype,
- str_getcharbuffer.api_func.get_wrapper(space))
+ c_buf.c_bf_getbuffer = llhelper(
+ str_getbuffer.api_func.functype,
+ str_getbuffer.api_func.get_wrapper(space))
pto.c_tp_as_buffer = c_buf
pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
-def setup_buffer_buffer_procs(space, pto):
- c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
- lltype.render_immortal(c_buf)
- c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype,
- str_segcount.api_func.get_wrapper(space))
- c_buf.c_bf_getreadbuffer = llhelper(buf_getreadbuffer.api_func.functype,
- buf_getreadbuffer.api_func.get_wrapper(space))
- pto.c_tp_as_buffer = c_buf
-
@cpython_api([PyObject], lltype.Void, external=False)
def type_dealloc(space, obj):
from pypy.module.cpyext.object import PyObject_dealloc
@@ -508,8 +459,6 @@
# buffer protocol
if space.is_w(w_type, space.w_str):
setup_string_buffer_procs(space, pto)
- if space.is_w(w_type, space.gettypefor(Buffer)):
- setup_buffer_buffer_procs(space, pto)
pto.c_tp_free = llhelper(PyObject_Del.api_func.functype,
PyObject_Del.api_func.get_wrapper(space))
diff --git a/pypy/module/cpyext/typeobjectdefs.py b/pypy/module/cpyext/typeobjectdefs.py
--- a/pypy/module/cpyext/typeobjectdefs.py
+++ b/pypy/module/cpyext/typeobjectdefs.py
@@ -1,7 +1,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP,
- PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP,
+ PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP, Py_buffer,
Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE)
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
from pypy.module.cpyext.modsupport import PyMethodDef
@@ -53,13 +53,8 @@
wrapperfunc = P(FT([PyO, PyO, rffi.VOIDP], PyO))
wrapperfunc_kwds = P(FT([PyO, PyO, rffi.VOIDP, PyO], PyO))
-readbufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
-writebufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
-segcountproc = P(FT([PyO, Py_ssize_tP], Py_ssize_t))
-charbufferproc = P(FT([PyO, Py_ssize_t, rffi.CCHARPP], Py_ssize_t))
-## We don't support new buffer interface for now
-getbufferproc = rffi.VOIDP
-releasebufferproc = rffi.VOIDP
+getbufferproc = P(FT([PyO, Ptr(Py_buffer), rffi.INT_real], rffi.INT_real))
+releasebufferproc = P(FT([PyO, Ptr(Py_buffer)], Void))
PyGetSetDef = cpython_struct("PyGetSetDef", (
@@ -131,10 +126,6 @@
))
PyBufferProcs = cpython_struct("PyBufferProcs", (
- ("bf_getreadbuffer", readbufferproc),
- ("bf_getwritebuffer", writebufferproc),
- ("bf_getsegcount", segcountproc),
- ("bf_getcharbuffer", charbufferproc),
("bf_getbuffer", getbufferproc),
("bf_releasebuffer", releasebufferproc),
))
More information about the pypy-commit
mailing list