Skip to content

gh-85275: Remove old buffer APIs #105137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Doc/c-api/abstract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,3 @@ but whose items have not been set to some non-\ ``NULL`` value yet.
mapping.rst
iter.rst
buffer.rst
objbuffer.rst
55 changes: 0 additions & 55 deletions Doc/c-api/objbuffer.rst

This file was deleted.

15 changes: 0 additions & 15 deletions Doc/data/refcounts.dat
Original file line number Diff line number Diff line change
Expand Up @@ -1578,21 +1578,6 @@ PyOS_FSPath:PyObject*:path:0:
PyObject_ASCII:PyObject*::+1:
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*:o:0:

Expand Down
4 changes: 0 additions & 4 deletions Doc/data/stable_abi.dat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,42 @@ Removed

(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,
deprecated in Python 3.11:

Expand Down
49 changes: 0 additions & 49 deletions Include/abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,55 +320,6 @@ PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, const char *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
obj.__format__(format_spec). */
PyAPI_FUNC(PyObject *) PyObject_Format(PyObject *obj,
Expand Down
Original file line number Diff line number Diff line change
@@ -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`.
4 changes: 4 additions & 0 deletions Misc/stable_abi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1755,12 +1755,16 @@

[function.PyObject_AsCharBuffer]
added = '3.2'
abi_only = true
[function.PyObject_AsReadBuffer]
added = '3.2'
abi_only = true
[function.PyObject_AsWriteBuffer]
added = '3.2'
abi_only = true
[function.PyObject_CheckReadBuffer]
added = '3.2'
abi_only = true

# Flags are implicitly part of the ABI:

Expand Down
44 changes: 35 additions & 9 deletions Objects/abstract.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,17 @@ PyObject_CheckBuffer(PyObject *obj)
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.
*/
int
PyAPI_FUNC(int) /* abi_only */
PyObject_CheckReadBuffer(PyObject *obj)
{
PyBufferProcs *pb = Py_TYPE(obj)->tp_as_buffer;
Expand Down Expand Up @@ -333,24 +339,44 @@ as_read_buffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len)
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,
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)
/* 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,
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)
/* 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,
Py_ssize_t *buffer_len)
{
PyBufferProcs *pb;
Py_buffer view;
Expand Down