Skip to content
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

gh-128863: Deprecate the private _PyUnicodeWriter API #129245

Merged
merged 11 commits into from
Feb 20, 2025
26 changes: 26 additions & 0 deletions Doc/deprecations/c-api-pending-removal-in-3.18.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@ Pending removal in Python 3.18
use :c:func:`PyLongWriter_Create`.
* :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`.
* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
* :c:func:`!_PyUnicodeWriter_Init`:
replace ``_PyUnicodeWriter_Init(&writer)`` with
:c:func:`writer = PyUnicodeWriter_Create(0) <PyUnicodeWriter_Create>`.
* :c:func:`!_PyUnicodeWriter_Finish`:
replace ``_PyUnicodeWriter_Finish(&writer)`` with
:c:func:`PyUnicodeWriter_Finish(writer) <PyUnicodeWriter_Finish>`.
* :c:func:`!_PyUnicodeWriter_Dealloc`:
replace ``_PyUnicodeWriter_Dealloc(&writer)`` with
:c:func:`PyUnicodeWriter_Discard(writer) <PyUnicodeWriter_Discard>`.
* :c:func:`!_PyUnicodeWriter_WriteChar`:
replace ``_PyUnicodeWriter_WriteChar(&writer, ch)`` with
:c:func:`PyUnicodeWriter_WriteChar(writer, ch) <PyUnicodeWriter_WriteChar>`.
* :c:func:`!_PyUnicodeWriter_WriteStr`:
replace ``_PyUnicodeWriter_WriteStr(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteStr(writer, str) <PyUnicodeWriter_WriteStr>`.
* :c:func:`!_PyUnicodeWriter_WriteSubstring`:
replace ``_PyUnicodeWriter_WriteSubstring(&writer, str, start, end)`` with
:c:func:`PyUnicodeWriter_WriteSubstring(writer, str, start, end) <PyUnicodeWriter_WriteSubstring>`.
* :c:func:`!_PyUnicodeWriter_WriteASCIIString`:
replace ``_PyUnicodeWriter_WriteASCIIString(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.
* :c:func:`!_PyUnicodeWriter_WriteLatin1String`:
replace ``_PyUnicodeWriter_WriteLatin1String(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.
* :c:func:`!_PyUnicodeWriter_Prepare`: (no replacement).
* :c:func:`!_PyUnicodeWriter_PrepareKind`: (no replacement).
* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
* :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`.

Expand Down
56 changes: 41 additions & 15 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1497,21 +1497,23 @@ Porting to Python 3.14

* Private functions promoted to public C APIs:

* ``_PyBytes_Join()``: :c:func:`PyBytes_Join`;
* ``_PyLong_IsNegative()``: :c:func:`PyLong_IsNegative`;
* ``_PyLong_IsPositive()``: :c:func:`PyLong_IsPositive`;
* ``_PyLong_IsZero()``: :c:func:`PyLong_IsZero`;
* ``_PyLong_Sign()``: :c:func:`PyLong_GetSign`;
* ``_PyUnicodeWriter_Dealloc()``: :c:func:`PyUnicodeWriter_Discard`;
* ``_PyUnicodeWriter_Finish()``: :c:func:`PyUnicodeWriter_Finish`;
* ``_PyUnicodeWriter_Init()``: :c:func:`PyUnicodeWriter_Create`;
* ``_PyUnicodeWriter_WriteChar()``: :c:func:`PyUnicodeWriter_WriteChar`;
* ``_PyUnicodeWriter_WriteStr()``: :c:func:`PyUnicodeWriter_WriteStr`;
* ``_PyUnicodeWriter_WriteSubstring()``: :c:func:`PyUnicodeWriter_WriteSubstring`;
* ``_PyUnicode_EQ()``: :c:func:`PyUnicode_Equal`;
* ``_PyUnicode_Equal()``: :c:func:`PyUnicode_Equal`;
* ``_Py_GetConfig()``: :c:func:`PyConfig_Get` and :c:func:`PyConfig_GetInt`;
* ``_Py_HashBytes()``: :c:func:`Py_HashBuffer`;
* ``_PyBytes_Join()``: :c:func:`PyBytes_Join`.
* ``_PyLong_IsNegative()``: :c:func:`PyLong_IsNegative`.
* ``_PyLong_IsPositive()``: :c:func:`PyLong_IsPositive`.
* ``_PyLong_IsZero()``: :c:func:`PyLong_IsZero`.
* ``_PyLong_Sign()``: :c:func:`PyLong_GetSign`.
* ``_PyUnicodeWriter_Dealloc()``: :c:func:`PyUnicodeWriter_Discard`.
* ``_PyUnicodeWriter_Finish()``: :c:func:`PyUnicodeWriter_Finish`.
* ``_PyUnicodeWriter_Init()``: use :c:func:`PyUnicodeWriter_Create`.
* ``_PyUnicodeWriter_Prepare()``: (no replacement).
* ``_PyUnicodeWriter_PrepareKind()``: (no replacement).
* ``_PyUnicodeWriter_WriteChar()``: :c:func:`PyUnicodeWriter_WriteChar`.
* ``_PyUnicodeWriter_WriteStr()``: :c:func:`PyUnicodeWriter_WriteStr`.
* ``_PyUnicodeWriter_WriteSubstring()``: :c:func:`PyUnicodeWriter_WriteSubstring`.
* ``_PyUnicode_EQ()``: :c:func:`PyUnicode_Equal`.
* ``_PyUnicode_Equal()``: :c:func:`PyUnicode_Equal`.
* ``_Py_GetConfig()``: :c:func:`PyConfig_Get` and :c:func:`PyConfig_GetInt`.
* ``_Py_HashBytes()``: :c:func:`Py_HashBuffer`.
* ``_Py_fopen_obj()``: :c:func:`Py_fopen`.

The `pythoncapi-compat project`_ can be used to get most of these new
Expand Down Expand Up @@ -1556,6 +1558,30 @@ Deprecated
use :c:func:`PyLongWriter_Create`.
* :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`.
* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`.
* :c:func:`!_PyUnicodeWriter_Init`:
replace ``_PyUnicodeWriter_Init(&writer)`` with
:c:func:`writer = PyUnicodeWriter_Create(0) <PyUnicodeWriter_Create>`.
* :c:func:`!_PyUnicodeWriter_Finish`:
replace ``_PyUnicodeWriter_Finish(&writer)`` with
:c:func:`PyUnicodeWriter_Finish(writer) <PyUnicodeWriter_Finish>`.
* :c:func:`!_PyUnicodeWriter_Dealloc`:
replace ``_PyUnicodeWriter_Dealloc(&writer)`` with
:c:func:`PyUnicodeWriter_Discard(writer) <PyUnicodeWriter_Discard>`.
* :c:func:`!_PyUnicodeWriter_WriteChar`:
replace ``_PyUnicodeWriter_WriteChar(&writer, ch)`` with
:c:func:`PyUnicodeWriter_WriteChar(writer, ch) <PyUnicodeWriter_WriteChar>`.
* :c:func:`!_PyUnicodeWriter_WriteStr`:
replace ``_PyUnicodeWriter_WriteStr(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteStr(writer, str) <PyUnicodeWriter_WriteStr>`.
* :c:func:`!_PyUnicodeWriter_WriteSubstring`:
replace ``_PyUnicodeWriter_WriteSubstring(&writer, str, start, end)`` with
:c:func:`PyUnicodeWriter_WriteSubstring(writer, str, start, end) <PyUnicodeWriter_WriteSubstring>`.
* :c:func:`!_PyUnicodeWriter_WriteASCIIString`:
replace ``_PyUnicodeWriter_WriteASCIIString(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.
* :c:func:`!_PyUnicodeWriter_WriteLatin1String`:
replace ``_PyUnicodeWriter_WriteLatin1String(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.
* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`.
* :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`.

Expand Down
60 changes: 28 additions & 32 deletions Include/cpython/unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,8 @@ typedef struct {
// By default, the minimum buffer size is 0 character and overallocation is
// disabled. Set min_length, min_char and overallocate attributes to control
// the allocation of the buffer.
PyAPI_FUNC(void)
_PyUnicodeWriter_Init(_PyUnicodeWriter *writer);
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(void) _PyUnicodeWriter_Init(
_PyUnicodeWriter *writer);

/* Prepare the buffer to write 'length' characters
with the specified maximum character.
Expand All @@ -547,9 +547,10 @@ _PyUnicodeWriter_Init(_PyUnicodeWriter *writer);

/* Don't call this function directly, use the _PyUnicodeWriter_Prepare() macro
instead. */
PyAPI_FUNC(int)
_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,
Py_ssize_t length, Py_UCS4 maxchar);
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(int) _PyUnicodeWriter_PrepareInternal(
_PyUnicodeWriter *writer,
Py_ssize_t length,
Py_UCS4 maxchar);

/* Prepare the buffer to have at least the kind KIND.
For example, kind=PyUnicode_2BYTE_KIND ensures that the writer will
Expand All @@ -563,58 +564,53 @@ _PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,

/* Don't call this function directly, use the _PyUnicodeWriter_PrepareKind()
macro instead. */
PyAPI_FUNC(int)
_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer,
int kind);
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(int) _PyUnicodeWriter_PrepareKindInternal(
_PyUnicodeWriter *writer,
int kind);

/* Append a Unicode character.
Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int)
_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer,
Py_UCS4 ch
);
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(int) _PyUnicodeWriter_WriteChar(
_PyUnicodeWriter *writer,
Py_UCS4 ch);

/* Append a Unicode string.
Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int)
_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer,
PyObject *str /* Unicode string */
);
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(int) _PyUnicodeWriter_WriteStr(
_PyUnicodeWriter *writer,
PyObject *str); /* Unicode string */

/* Append a substring of a Unicode string.
Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int)
_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer,
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(int) _PyUnicodeWriter_WriteSubstring(
_PyUnicodeWriter *writer,
PyObject *str, /* Unicode string */
Py_ssize_t start,
Py_ssize_t end
);
Py_ssize_t end);

/* Append an ASCII-encoded byte string.
Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int)
_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(int) _PyUnicodeWriter_WriteASCIIString(
_PyUnicodeWriter *writer,
const char *str, /* ASCII-encoded byte string */
Py_ssize_t len /* number of bytes, or -1 if unknown */
);
Py_ssize_t len); /* number of bytes, or -1 if unknown */

/* Append a latin1-encoded byte string.
Return 0 on success, raise an exception and return -1 on error. */
PyAPI_FUNC(int)
_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer,
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(int) _PyUnicodeWriter_WriteLatin1String(
_PyUnicodeWriter *writer,
const char *str, /* latin1-encoded byte string */
Py_ssize_t len /* length in bytes */
);
Py_ssize_t len); /* length in bytes */

/* Get the value of the writer as a Unicode string. Clear the
buffer of the writer. Raise an exception and return NULL
on error. */
PyAPI_FUNC(PyObject *)
_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer);
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(PyObject *) _PyUnicodeWriter_Finish(
_PyUnicodeWriter *writer);

/* Deallocate memory of a writer (clear its internal buffer). */
PyAPI_FUNC(void)
_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer);
_Py_DEPRECATED_EXTERNALLY(3.14) PyAPI_FUNC(void) _PyUnicodeWriter_Dealloc(
_PyUnicodeWriter *writer);


/* --- Manage the default encoding ---------------------------------------- */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
The following private functions are deprecated and planned for removal in
Python 3.18:

* :c:func:`!_PyUnicodeWriter_Init`:
replace ``_PyUnicodeWriter_Init(&writer)`` with
:c:func:`writer = PyUnicodeWriter_Create(0) <PyUnicodeWriter_Create>`.
* :c:func:`!_PyUnicodeWriter_Finish`:
replace ``_PyUnicodeWriter_Finish(&writer)`` with
:c:func:`PyUnicodeWriter_Finish(writer) <PyUnicodeWriter_Finish>`.
* :c:func:`!_PyUnicodeWriter_Dealloc`:
replace ``_PyUnicodeWriter_Dealloc(&writer)`` with
:c:func:`PyUnicodeWriter_Discard(writer) <PyUnicodeWriter_Discard>`.
* :c:func:`!_PyUnicodeWriter_WriteChar`:
replace ``_PyUnicodeWriter_WriteChar(&writer, ch)`` with
:c:func:`PyUnicodeWriter_WriteChar(writer, ch) <PyUnicodeWriter_WriteChar>`.
* :c:func:`!_PyUnicodeWriter_WriteStr`:
replace ``_PyUnicodeWriter_WriteStr(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteStr(writer, str) <PyUnicodeWriter_WriteStr>`.
* :c:func:`!_PyUnicodeWriter_WriteSubstring`:
replace ``_PyUnicodeWriter_WriteSubstring(&writer, str, start, end)`` with
:c:func:`PyUnicodeWriter_WriteSubstring(writer, str, start, end) <PyUnicodeWriter_WriteSubstring>`.
* :c:func:`!_PyUnicodeWriter_WriteASCIIString`:
replace ``_PyUnicodeWriter_WriteASCIIString(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.
* :c:func:`!_PyUnicodeWriter_WriteLatin1String`:
replace ``_PyUnicodeWriter_WriteLatin1String(&writer, str)`` with
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.
* :c:func:`!_PyUnicodeWriter_Prepare`: (no replacement).
* :c:func:`!_PyUnicodeWriter_PrepareKind`: (no replacement).

The `pythoncapi-compat project
<https://github.com/python/pythoncapi-compat/>`__ can be used to get these
new public functions on Python 3.13 and older.

Patch by Victor Stinner.
Loading