mirror of
https://github.com/python/cpython
synced 2024-09-05 16:38:56 +00:00
bpo-41103: Resurrect the old buffer protocol. (GH-27437)
Revert "bpo-41103: Remove old buffer protocol support (#21117)"
This reverts commit 6f8a6ee59c
.
This commit is contained in:
parent
d542742128
commit
ce5e1a6809
|
@ -24,3 +24,4 @@ but whose items have not been set to some non-\ ``NULL`` value yet.
|
||||||
mapping.rst
|
mapping.rst
|
||||||
iter.rst
|
iter.rst
|
||||||
buffer.rst
|
buffer.rst
|
||||||
|
objbuffer.rst
|
||||||
|
|
55
Doc/c-api/objbuffer.rst
Normal file
55
Doc/c-api/objbuffer.rst
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
.. highlight:: c
|
||||||
|
|
||||||
|
Old Buffer Protocol
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. deprecated:: 3.0
|
||||||
|
|
||||||
|
These functions were part of the "old buffer protocol" API in Python 2.
|
||||||
|
In Python 3, this protocol doesn't exist anymore but the functions are still
|
||||||
|
exposed to ease porting 2.x code. They act as a compatibility wrapper
|
||||||
|
around the :ref:`new buffer protocol <bufferobjects>`, but they don't give
|
||||||
|
you control over the lifetime of the resources acquired when a buffer is
|
||||||
|
exported.
|
||||||
|
|
||||||
|
Therefore, it is recommended that you call :c:func:`PyObject_GetBuffer`
|
||||||
|
(or the ``y*`` or ``w*`` :ref:`format codes <arg-parsing>` with the
|
||||||
|
:c:func:`PyArg_ParseTuple` family of functions) to get a buffer view over
|
||||||
|
an object, and :c:func:`PyBuffer_Release` when the buffer view can be released.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: int PyObject_AsCharBuffer(PyObject *obj, const char **buffer, Py_ssize_t *buffer_len)
|
||||||
|
|
||||||
|
Returns a pointer to a read-only memory location usable as character-based
|
||||||
|
input. The *obj* argument must support the single-segment character buffer
|
||||||
|
interface. On success, returns ``0``, sets *buffer* to the memory location
|
||||||
|
and *buffer_len* to the buffer length. Returns ``-1`` and sets a
|
||||||
|
:exc:`TypeError` on error.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: int PyObject_AsReadBuffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len)
|
||||||
|
|
||||||
|
Returns a pointer to a read-only memory location containing arbitrary data.
|
||||||
|
The *obj* argument must support the single-segment readable buffer
|
||||||
|
interface. On success, returns ``0``, sets *buffer* to the memory location
|
||||||
|
and *buffer_len* to the buffer length. Returns ``-1`` and sets a
|
||||||
|
:exc:`TypeError` on error.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: int PyObject_CheckReadBuffer(PyObject *o)
|
||||||
|
|
||||||
|
Returns ``1`` if *o* supports the single-segment readable buffer interface.
|
||||||
|
Otherwise returns ``0``. This function always succeeds.
|
||||||
|
|
||||||
|
Note that this function tries to get and release a buffer, and exceptions
|
||||||
|
which occur while calling corresponding functions will get suppressed.
|
||||||
|
To get error reporting use :c:func:`PyObject_GetBuffer()` instead.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: int PyObject_AsWriteBuffer(PyObject *obj, void **buffer, Py_ssize_t *buffer_len)
|
||||||
|
|
||||||
|
Returns a pointer to a writable memory location. The *obj* argument must
|
||||||
|
support the single-segment, character buffer interface. On success,
|
||||||
|
returns ``0``, sets *buffer* to the memory location and *buffer_len* to the
|
||||||
|
buffer length. Returns ``-1`` and sets a :exc:`TypeError` on error.
|
||||||
|
|
|
@ -1571,6 +1571,21 @@ PyOS_FSPath:PyObject*:path:0:
|
||||||
PyObject_ASCII:PyObject*::+1:
|
PyObject_ASCII:PyObject*::+1:
|
||||||
PyObject_ASCII:PyObject*:o:0:
|
PyObject_ASCII:PyObject*:o:0:
|
||||||
|
|
||||||
|
PyObject_AsCharBuffer:int:::
|
||||||
|
PyObject_AsCharBuffer:PyObject*:obj:0:
|
||||||
|
PyObject_AsCharBuffer:const char**:buffer::
|
||||||
|
PyObject_AsCharBuffer:Py_ssize_t*:buffer_len::
|
||||||
|
|
||||||
|
PyObject_AsReadBuffer:int:::
|
||||||
|
PyObject_AsReadBuffer:PyObject*:obj:0:
|
||||||
|
PyObject_AsReadBuffer:const void**:buffer::
|
||||||
|
PyObject_AsReadBuffer:Py_ssize_t*:buffer_len::
|
||||||
|
|
||||||
|
PyObject_AsWriteBuffer:int:::
|
||||||
|
PyObject_AsWriteBuffer:PyObject*:obj:0:
|
||||||
|
PyObject_AsWriteBuffer:void**:buffer::
|
||||||
|
PyObject_AsWriteBuffer:Py_ssize_t*:buffer_len::
|
||||||
|
|
||||||
PyObject_Bytes:PyObject*::+1:
|
PyObject_Bytes:PyObject*::+1:
|
||||||
PyObject_Bytes:PyObject*:o:0:
|
PyObject_Bytes:PyObject*:o:0:
|
||||||
|
|
||||||
|
@ -1606,6 +1621,9 @@ PyObject_CallObject:PyObject*:args:0:
|
||||||
PyObject_CheckBuffer:int:::
|
PyObject_CheckBuffer:int:::
|
||||||
PyObject_CheckBuffer:PyObject*:obj:0:
|
PyObject_CheckBuffer:PyObject*:obj:0:
|
||||||
|
|
||||||
|
PyObject_CheckReadBuffer:int:::
|
||||||
|
PyObject_CheckReadBuffer:PyObject*:o:0:
|
||||||
|
|
||||||
PyObject_DelAttr:int:::
|
PyObject_DelAttr:int:::
|
||||||
PyObject_DelAttr:PyObject*:o:0:
|
PyObject_DelAttr:PyObject*:o:0:
|
||||||
PyObject_DelAttr:PyObject*:attr_name:0:
|
PyObject_DelAttr:PyObject*:attr_name:0:
|
||||||
|
|
|
@ -462,7 +462,10 @@ function,PyOS_strtoul,3.2,
|
||||||
function,PyOS_vsnprintf,3.2,
|
function,PyOS_vsnprintf,3.2,
|
||||||
type,PyObject,3.2,
|
type,PyObject,3.2,
|
||||||
function,PyObject_ASCII,3.2,
|
function,PyObject_ASCII,3.2,
|
||||||
|
function,PyObject_AsCharBuffer,3.2,
|
||||||
function,PyObject_AsFileDescriptor,3.2,
|
function,PyObject_AsFileDescriptor,3.2,
|
||||||
|
function,PyObject_AsReadBuffer,3.2,
|
||||||
|
function,PyObject_AsWriteBuffer,3.2,
|
||||||
function,PyObject_Bytes,3.2,
|
function,PyObject_Bytes,3.2,
|
||||||
function,PyObject_Call,3.2,
|
function,PyObject_Call,3.2,
|
||||||
function,PyObject_CallFunction,3.2,
|
function,PyObject_CallFunction,3.2,
|
||||||
|
@ -472,6 +475,7 @@ function,PyObject_CallMethodObjArgs,3.2,
|
||||||
function,PyObject_CallNoArgs,3.10,
|
function,PyObject_CallNoArgs,3.10,
|
||||||
function,PyObject_CallObject,3.2,
|
function,PyObject_CallObject,3.2,
|
||||||
function,PyObject_Calloc,3.7,
|
function,PyObject_Calloc,3.7,
|
||||||
|
function,PyObject_CheckReadBuffer,3.2,
|
||||||
function,PyObject_ClearWeakRefs,3.2,
|
function,PyObject_ClearWeakRefs,3.2,
|
||||||
function,PyObject_DelItem,3.2,
|
function,PyObject_DelItem,3.2,
|
||||||
function,PyObject_DelItemString,3.2,
|
function,PyObject_DelItemString,3.2,
|
||||||
|
|
|
@ -2113,11 +2113,6 @@ Deprecated
|
||||||
Removed
|
Removed
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* ``PyObject_AsCharBuffer()``, ``PyObject_AsReadBuffer()``, ``PyObject_CheckReadBuffer()``,
|
|
||||||
and ``PyObject_AsWriteBuffer()`` are removed. Please migrate to new buffer protocol;
|
|
||||||
:c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release`.
|
|
||||||
(Contributed by Inada Naoki in :issue:`41103`.)
|
|
||||||
|
|
||||||
* Removed ``Py_UNICODE_str*`` functions manipulating ``Py_UNICODE*`` strings.
|
* Removed ``Py_UNICODE_str*`` functions manipulating ``Py_UNICODE*`` strings.
|
||||||
(Contributed by Inada Naoki in :issue:`41123`.)
|
(Contributed by Inada Naoki in :issue:`41123`.)
|
||||||
|
|
||||||
|
|
|
@ -309,6 +309,53 @@ PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, const char *key);
|
||||||
PyAPI_FUNC(int) PyObject_DelItem(PyObject *o, PyObject *key);
|
PyAPI_FUNC(int) PyObject_DelItem(PyObject *o, PyObject *key);
|
||||||
|
|
||||||
|
|
||||||
|
/* === Old Buffer API ============================================ */
|
||||||
|
|
||||||
|
/* FIXME: usage of these should all be replaced in Python itself
|
||||||
|
but for backwards compatibility we will implement them.
|
||||||
|
Their usage without a corresponding "unlock" mechanism
|
||||||
|
may create issues (but they would already be there). */
|
||||||
|
|
||||||
|
/* Takes an arbitrary object which must support the (character, single segment)
|
||||||
|
buffer interface and returns a pointer to a read-only memory location
|
||||||
|
useable as character based input for subsequent processing.
|
||||||
|
|
||||||
|
Return 0 on success. buffer and buffer_len are only set in case no error
|
||||||
|
occurs. Otherwise, -1 is returned and an exception set. */
|
||||||
|
Py_DEPRECATED(3.0)
|
||||||
|
PyAPI_FUNC(int) PyObject_AsCharBuffer(PyObject *obj,
|
||||||
|
const char **buffer,
|
||||||
|
Py_ssize_t *buffer_len);
|
||||||
|
|
||||||
|
/* Checks whether an arbitrary object supports the (character, single segment)
|
||||||
|
buffer interface.
|
||||||
|
|
||||||
|
Returns 1 on success, 0 on failure. */
|
||||||
|
Py_DEPRECATED(3.0) PyAPI_FUNC(int) PyObject_CheckReadBuffer(PyObject *obj);
|
||||||
|
|
||||||
|
/* Same as PyObject_AsCharBuffer() except that this API expects (readable,
|
||||||
|
single segment) buffer interface and returns a pointer to a read-only memory
|
||||||
|
location which can contain arbitrary data.
|
||||||
|
|
||||||
|
0 is returned on success. buffer and buffer_len are only set in case no
|
||||||
|
error occurs. Otherwise, -1 is returned and an exception set. */
|
||||||
|
Py_DEPRECATED(3.0)
|
||||||
|
PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *obj,
|
||||||
|
const void **buffer,
|
||||||
|
Py_ssize_t *buffer_len);
|
||||||
|
|
||||||
|
/* Takes an arbitrary object which must support the (writable, single segment)
|
||||||
|
buffer interface and returns a pointer to a writable memory location in
|
||||||
|
buffer of size 'buffer_len'.
|
||||||
|
|
||||||
|
Return 0 on success. buffer and buffer_len are only set in case no error
|
||||||
|
occurs. Otherwise, -1 is returned and an exception set. */
|
||||||
|
Py_DEPRECATED(3.0)
|
||||||
|
PyAPI_FUNC(int) PyObject_AsWriteBuffer(PyObject *obj,
|
||||||
|
void **buffer,
|
||||||
|
Py_ssize_t *buffer_len);
|
||||||
|
|
||||||
|
|
||||||
/* === New Buffer API ============================================ */
|
/* === New Buffer API ============================================ */
|
||||||
|
|
||||||
/* Takes an arbitrary object and returns the result of calling
|
/* Takes an arbitrary object and returns the result of calling
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Reverts removal of the old buffer protocol because they are part of stable
|
||||||
|
ABI.
|
|
@ -1642,6 +1642,17 @@ function _Py_VaBuildValue_SizeT
|
||||||
added 3.2
|
added 3.2
|
||||||
abi_only
|
abi_only
|
||||||
|
|
||||||
|
# Old buffer protocol support (deprecated)
|
||||||
|
|
||||||
|
function PyObject_AsCharBuffer
|
||||||
|
added 3.2
|
||||||
|
function PyObject_AsReadBuffer
|
||||||
|
added 3.2
|
||||||
|
function PyObject_AsWriteBuffer
|
||||||
|
added 3.2
|
||||||
|
function PyObject_CheckReadBuffer
|
||||||
|
added 3.2
|
||||||
|
|
||||||
# Flags are implicitly part of the ABI:
|
# Flags are implicitly part of the ABI:
|
||||||
|
|
||||||
const Py_TPFLAGS_DEFAULT
|
const Py_TPFLAGS_DEFAULT
|
||||||
|
|
|
@ -293,6 +293,85 @@ PyObject_CheckBuffer(PyObject *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* We release the buffer right after use of this function which could
|
||||||
|
cause issues later on. Don't use these functions in new code.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
PyObject_CheckReadBuffer(PyObject *obj)
|
||||||
|
{
|
||||||
|
PyBufferProcs *pb = Py_TYPE(obj)->tp_as_buffer;
|
||||||
|
Py_buffer view;
|
||||||
|
|
||||||
|
if (pb == NULL ||
|
||||||
|
pb->bf_getbuffer == NULL)
|
||||||
|
return 0;
|
||||||
|
if ((*pb->bf_getbuffer)(obj, &view, PyBUF_SIMPLE) == -1) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
PyBuffer_Release(&view);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
as_read_buffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len)
|
||||||
|
{
|
||||||
|
Py_buffer view;
|
||||||
|
|
||||||
|
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
|
||||||
|
null_error();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*buffer = view.buf;
|
||||||
|
*buffer_len = view.len;
|
||||||
|
PyBuffer_Release(&view);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyObject_AsCharBuffer(PyObject *obj,
|
||||||
|
const char **buffer,
|
||||||
|
Py_ssize_t *buffer_len)
|
||||||
|
{
|
||||||
|
return as_read_buffer(obj, (const void **)buffer, buffer_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PyObject_AsReadBuffer(PyObject *obj,
|
||||||
|
const void **buffer,
|
||||||
|
Py_ssize_t *buffer_len)
|
||||||
|
{
|
||||||
|
return as_read_buffer(obj, buffer, buffer_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PyObject_AsWriteBuffer(PyObject *obj,
|
||||||
|
void **buffer,
|
||||||
|
Py_ssize_t *buffer_len)
|
||||||
|
{
|
||||||
|
PyBufferProcs *pb;
|
||||||
|
Py_buffer view;
|
||||||
|
|
||||||
|
if (obj == NULL || buffer == NULL || buffer_len == NULL) {
|
||||||
|
null_error();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pb = Py_TYPE(obj)->tp_as_buffer;
|
||||||
|
if (pb == NULL ||
|
||||||
|
pb->bf_getbuffer == NULL ||
|
||||||
|
((*pb->bf_getbuffer)(obj, &view, PyBUF_WRITABLE) != 0)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"expected a writable bytes-like object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*buffer = view.buf;
|
||||||
|
*buffer_len = view.len;
|
||||||
|
PyBuffer_Release(&view);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Buffer C-API for Python 3.0 */
|
/* Buffer C-API for Python 3.0 */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -413,8 +413,11 @@ EXPORT_FUNC(PyNumber_Subtract)
|
||||||
EXPORT_FUNC(PyNumber_ToBase)
|
EXPORT_FUNC(PyNumber_ToBase)
|
||||||
EXPORT_FUNC(PyNumber_TrueDivide)
|
EXPORT_FUNC(PyNumber_TrueDivide)
|
||||||
EXPORT_FUNC(PyNumber_Xor)
|
EXPORT_FUNC(PyNumber_Xor)
|
||||||
|
EXPORT_FUNC(PyObject_AsCharBuffer)
|
||||||
EXPORT_FUNC(PyObject_ASCII)
|
EXPORT_FUNC(PyObject_ASCII)
|
||||||
EXPORT_FUNC(PyObject_AsFileDescriptor)
|
EXPORT_FUNC(PyObject_AsFileDescriptor)
|
||||||
|
EXPORT_FUNC(PyObject_AsReadBuffer)
|
||||||
|
EXPORT_FUNC(PyObject_AsWriteBuffer)
|
||||||
EXPORT_FUNC(PyObject_Bytes)
|
EXPORT_FUNC(PyObject_Bytes)
|
||||||
EXPORT_FUNC(PyObject_Call)
|
EXPORT_FUNC(PyObject_Call)
|
||||||
EXPORT_FUNC(PyObject_CallFunction)
|
EXPORT_FUNC(PyObject_CallFunction)
|
||||||
|
@ -424,6 +427,7 @@ EXPORT_FUNC(PyObject_CallMethodObjArgs)
|
||||||
EXPORT_FUNC(PyObject_CallNoArgs)
|
EXPORT_FUNC(PyObject_CallNoArgs)
|
||||||
EXPORT_FUNC(PyObject_CallObject)
|
EXPORT_FUNC(PyObject_CallObject)
|
||||||
EXPORT_FUNC(PyObject_Calloc)
|
EXPORT_FUNC(PyObject_Calloc)
|
||||||
|
EXPORT_FUNC(PyObject_CheckReadBuffer)
|
||||||
EXPORT_FUNC(PyObject_ClearWeakRefs)
|
EXPORT_FUNC(PyObject_ClearWeakRefs)
|
||||||
EXPORT_FUNC(PyObject_DelItem)
|
EXPORT_FUNC(PyObject_DelItem)
|
||||||
EXPORT_FUNC(PyObject_DelItemString)
|
EXPORT_FUNC(PyObject_DelItemString)
|
||||||
|
|
Loading…
Reference in a new issue