gh-85275: Remove old buffer APIs (#105137)

They are now abi-only.

Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Inada Naoki 2023-06-02 10:12:40 +09:00 committed by GitHub
parent ef300937c2
commit 37498fc950
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 79 additions and 133 deletions

View File

@ -24,4 +24,3 @@ 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

View File

@ -1,55 +0,0 @@
.. 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.

View File

@ -1578,21 +1578,6 @@ 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:

View File

@ -476,10 +476,7 @@ type,PyObject,3.2,,members
member,PyObject.ob_refcnt,3.2,, member,PyObject.ob_refcnt,3.2,,
member,PyObject.ob_type,3.2,, member,PyObject.ob_type,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,,
@ -490,7 +487,6 @@ 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_CheckBuffer,3.11,, function,PyObject_CheckBuffer,3.11,,
function,PyObject_CheckReadBuffer,3.2,,
function,PyObject_ClearWeakRefs,3.2,, function,PyObject_ClearWeakRefs,3.2,,
function,PyObject_CopyData,3.11,, function,PyObject_CopyData,3.11,,
function,PyObject_DelItem,3.2,, function,PyObject_DelItem,3.2,,

View File

@ -395,6 +395,42 @@ Removed
(Contributed by Victor Stinner in :gh:`105107`.) (Contributed by Victor Stinner in :gh:`105107`.)
* Remove old buffer protocols deprecated in Python 3.0. Use :ref:`bufferobjects` instead.
* :c:func:`!PyObject_CheckReadBuffer`: Use :c:func:`PyObject_CheckBuffer` to
test if the object supports the buffer protocol.
Note that :c:func:`PyObject_CheckBuffer` doesn't guarantee that
:c:func:`PyObject_GetBuffer` will succeed.
To test if the object is actually readable, see the next example
of :c:func:`PyObject_GetBuffer`.
* :c:func:`!PyObject_AsCharBuffer`, :c:func:`!PyObject_AsReadBuffer`:
:c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead:
.. code-block:: c
Py_buffer view;
if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) < 0) {
return NULL;
}
// Use `view.buf` and `view.len` to read from the buffer.
// You may need to cast buf as `(const char*)view.buf`.
PyBuffer_Release(&view);
* :c:func:`!PyObject_AsWriteBuffer`: Use
:c:func:`PyObject_GetBuffer` and :c:func:`PyBuffer_Release` instead:
.. code-block:: c
Py_buffer view;
if (PyObject_GetBuffer(obj, &view, PyBUF_WRITABLE) < 0) {
return NULL;
}
// Use `view.buf` and `view.len` to write to the buffer.
PyBuffer_Release(&view);
(Contributed by Inada Naoki in :gh:`85275`.)
* Remove the following old functions to configure the Python initialization, * Remove the following old functions to configure the Python initialization,
deprecated in Python 3.11: deprecated in Python 3.11:

View File

@ -320,55 +320,6 @@ 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
usable 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 ============================================ */
/* Takes an arbitrary object and returns the result of calling /* Takes an arbitrary object and returns the result of calling
obj.__format__(format_spec). */ obj.__format__(format_spec). */
PyAPI_FUNC(PyObject *) PyObject_Format(PyObject *obj, PyAPI_FUNC(PyObject *) PyObject_Format(PyObject *obj,

View File

@ -0,0 +1,4 @@
``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`.

View File

@ -1755,12 +1755,16 @@
[function.PyObject_AsCharBuffer] [function.PyObject_AsCharBuffer]
added = '3.2' added = '3.2'
abi_only = true
[function.PyObject_AsReadBuffer] [function.PyObject_AsReadBuffer]
added = '3.2' added = '3.2'
abi_only = true
[function.PyObject_AsWriteBuffer] [function.PyObject_AsWriteBuffer]
added = '3.2' added = '3.2'
abi_only = true
[function.PyObject_CheckReadBuffer] [function.PyObject_CheckReadBuffer]
added = '3.2' added = '3.2'
abi_only = true
# Flags are implicitly part of the ABI: # Flags are implicitly part of the ABI:

View File

@ -294,11 +294,17 @@ PyObject_CheckBuffer(PyObject *obj)
return (tp_as_buffer != NULL && tp_as_buffer->bf_getbuffer != NULL); return (tp_as_buffer != NULL && tp_as_buffer->bf_getbuffer != NULL);
} }
// Old buffer protocols (deprecated, abi only)
/* We release the buffer right after use of this function which could /* Checks whether an arbitrary object supports the (character, single segment)
buffer interface.
Returns 1 on success, 0 on failure.
We release the buffer right after use of this function which could
cause issues later on. Don't use these functions in new code. cause issues later on. Don't use these functions in new code.
*/ */
int PyAPI_FUNC(int) /* abi_only */
PyObject_CheckReadBuffer(PyObject *obj) PyObject_CheckReadBuffer(PyObject *obj)
{ {
PyBufferProcs *pb = Py_TYPE(obj)->tp_as_buffer; PyBufferProcs *pb = Py_TYPE(obj)->tp_as_buffer;
@ -333,7 +339,13 @@ as_read_buffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len)
return 0; return 0;
} }
int /* Takes an arbitrary object which must support the (character, single segment)
buffer interface and returns a pointer to a read-only memory location
usable 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. */
PyAPI_FUNC(int) /* abi_only */
PyObject_AsCharBuffer(PyObject *obj, PyObject_AsCharBuffer(PyObject *obj,
const char **buffer, const char **buffer,
Py_ssize_t *buffer_len) Py_ssize_t *buffer_len)
@ -341,14 +353,28 @@ PyObject_AsCharBuffer(PyObject *obj,
return as_read_buffer(obj, (const void **)buffer, buffer_len); return as_read_buffer(obj, (const void **)buffer, buffer_len);
} }
int PyObject_AsReadBuffer(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. */
PyAPI_FUNC(int) /* abi_only */
PyObject_AsReadBuffer(PyObject *obj,
const void **buffer, const void **buffer,
Py_ssize_t *buffer_len) Py_ssize_t *buffer_len)
{ {
return as_read_buffer(obj, buffer, buffer_len); return as_read_buffer(obj, buffer, buffer_len);
} }
int PyObject_AsWriteBuffer(PyObject *obj, /* 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. */
PyAPI_FUNC(int) /* abi_only */
PyObject_AsWriteBuffer(PyObject *obj,
void **buffer, void **buffer,
Py_ssize_t *buffer_len) Py_ssize_t *buffer_len)
{ {