Skip to content

Commit 1dc045c

Browse files
vstinner
committed
Replace most PyUnicodeWriter_WriteUTF8() calls with PyUnicodeWriter_WriteASCII(). Unrelated change to please the linter: remove an unused import in test_ctypes. Co-authored-by: Peter Bierma <zintensitydev@gmail.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> (cherry picked from commit f49a07b)
1 parent 6c917cb commit 1dc045c

File tree

17 files changed

+98
-32
lines changed
  • Doc
    • c-api
      • Original file line numberDiff line numberDiff line change
        @@ -1806,9 +1806,24 @@ object.
        18061806
        18071807
        See also :c:func:`PyUnicodeWriter_DecodeUTF8Stateful`.
        18081808
        1809+
        .. c:function:: int PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer, const char *str, Py_ssize_t size)
        1810+
        1811+
        Write the ASCII string *str* into *writer*.
        1812+
        1813+
        *size* is the string length in bytes. If *size* is equal to ``-1``, call
        1814+
        ``strlen(str)`` to get the string length.
        1815+
        1816+
        *str* must only contain ASCII characters. The behavior is undefined if
        1817+
        *str* contains non-ASCII characters.
        1818+
        1819+
        On success, return ``0``.
        1820+
        On error, set an exception, leave the writer unchanged, and return ``-1``.
        1821+
        1822+
        .. versionadded:: next
        1823+
        18091824
        .. c:function:: int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size)
        18101825
        1811-
        Writer the wide string *str* into *writer*.
        1826+
        Write the wide string *str* into *writer*.
        18121827
        18131828
        *size* is a number of wide characters. If *size* is equal to ``-1``, call
        18141829
        ``wcslen(str)`` to get the string length.

Doc/whatsnew/3.14.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2542,6 +2542,7 @@ New features
25422542
* :c:func:`PyUnicodeWriter_Discard`
25432543
* :c:func:`PyUnicodeWriter_Finish`
25442544
* :c:func:`PyUnicodeWriter_Format`
2545+
* :c:func:`PyUnicodeWriter_WriteASCII`
25452546
* :c:func:`PyUnicodeWriter_WriteChar`
25462547
* :c:func:`PyUnicodeWriter_WriteRepr`
25472548
* :c:func:`PyUnicodeWriter_WriteStr`
@@ -2818,7 +2819,7 @@ Deprecated
28182819
:c:func:`PyUnicodeWriter_WriteSubstring(writer, str, start, end) <PyUnicodeWriter_WriteSubstring>`.
28192820
* :c:func:`!_PyUnicodeWriter_WriteASCIIString`:
28202821
replace ``_PyUnicodeWriter_WriteASCIIString(&writer, str)`` with
2821-
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.
2822+
:c:func:`PyUnicodeWriter_WriteASCII(writer, str) <PyUnicodeWriter_WriteASCII>`.
28222823
* :c:func:`!_PyUnicodeWriter_WriteLatin1String`:
28232824
replace ``_PyUnicodeWriter_WriteLatin1String(&writer, str)`` with
28242825
:c:func:`PyUnicodeWriter_WriteUTF8(writer, str) <PyUnicodeWriter_WriteUTF8>`.

Include/cpython/unicodeobject.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,10 @@ PyAPI_FUNC(int) PyUnicodeWriter_WriteUTF8(
478478
PyUnicodeWriter *writer,
479479
const char *str,
480480
Py_ssize_t size);
481+
PyAPI_FUNC(int) PyUnicodeWriter_WriteASCII(
482+
PyUnicodeWriter *writer,
483+
const char *str,
484+
Py_ssize_t size);
481485
PyAPI_FUNC(int) PyUnicodeWriter_WriteWideChar(
482486
PyUnicodeWriter *writer,
483487
const wchar_t *str,

Lib/test/test_capi/test_unicode.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,13 @@ def test_utf8(self):
17761776
self.assertEqual(writer.finish(),
17771777
"ascii-latin1=\xE9-euro=\u20AC.")
17781778

1779+
def test_ascii(self):
1780+
writer = self.create_writer(0)
1781+
writer.write_ascii(b"Hello ", -1)
1782+
writer.write_ascii(b"", 0)
1783+
writer.write_ascii(b"Python! <truncated>", 6)
1784+
self.assertEqual(writer.finish(), "Hello Python")
1785+
17791786
def test_invalid_utf8(self):
17801787
writer = self.create_writer(0)
17811788
with self.assertRaises(UnicodeDecodeError):

Lib/test/test_ctypes/test_incomplete.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import ctypes
22
import unittest
3-
import warnings
43
from ctypes import Structure, POINTER, pointer, c_char_p
54

65
# String-based "incomplete pointers" were implemented in ctypes 0.6.3 (2003, when
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Add :c:func:`PyUnicodeWriter_WriteASCII` function to write an ASCII string
2+
into a :c:type:`PyUnicodeWriter`. The function is faster than
3+
:c:func:`PyUnicodeWriter_WriteUTF8`, but has an undefined behavior if the
4+
input string contains non-ASCII characters. Patch by Victor Stinner.

Modules/_json.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,13 +1476,13 @@ encoder_listencode_obj(PyEncoderObject *s, PyUnicodeWriter *writer,
14761476
int rv;
14771477

14781478
if (obj == Py_None) {
1479-
return PyUnicodeWriter_WriteUTF8(writer, "null", 4);
1479+
return PyUnicodeWriter_WriteASCII(writer, "null", 4);
14801480
}
14811481
else if (obj == Py_True) {
1482-
return PyUnicodeWriter_WriteUTF8(writer, "true", 4);
1482+
return PyUnicodeWriter_WriteASCII(writer, "true", 4);
14831483
}
14841484
else if (obj == Py_False) {
1485-
return PyUnicodeWriter_WriteUTF8(writer, "false", 5);
1485+
return PyUnicodeWriter_WriteASCII(writer, "false", 5);
14861486
}
14871487
else if (PyUnicode_Check(obj)) {
14881488
PyObject *encoded = encoder_encode_string(s, obj);
@@ -1649,7 +1649,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
16491649

16501650
if (PyDict_GET_SIZE(dct) == 0) {
16511651
/* Fast path */
1652-
return PyUnicodeWriter_WriteUTF8(writer, "{}", 2);
1652+
return PyUnicodeWriter_WriteASCII(writer, "{}", 2);
16531653
}
16541654

16551655
if (s->markers != Py_None) {
@@ -1753,7 +1753,7 @@ encoder_listencode_list(PyEncoderObject *s, PyUnicodeWriter *writer,
17531753
return -1;
17541754
if (PySequence_Fast_GET_SIZE(s_fast) == 0) {
17551755
Py_DECREF(s_fast);
1756-
return PyUnicodeWriter_WriteUTF8(writer, "[]", 2);
1756+
return PyUnicodeWriter_WriteASCII(writer, "[]", 2);
17571757
}
17581758

17591759
if (s->markers != Py_None) {

Modules/_ssl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ fill_and_set_sslerror(_sslmodulestate *state,
563563
goto fail;
564564
}
565565
}
566-
if (PyUnicodeWriter_WriteUTF8(writer, "] ", 2) < 0) {
566+
if (PyUnicodeWriter_WriteASCII(writer, "] ", 2) < 0) {
567567
goto fail;
568568
}
569569
}

Modules/_testcapi/unicode.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,27 @@ writer_write_utf8(PyObject *self_raw, PyObject *args)
332332
}
333333

334334

335+
static PyObject*
336+
writer_write_ascii(PyObject *self_raw, PyObject *args)
337+
{
338+
WriterObject *self = (WriterObject *)self_raw;
339+
if (writer_check(self) < 0) {
340+
return NULL;
341+
}
342+
343+
char *str;
344+
Py_ssize_t size;
345+
if (!PyArg_ParseTuple(args, "yn", &str, &size)) {
346+
return NULL;
347+
}
348+
349+
if (PyUnicodeWriter_WriteASCII(self->writer, str, size) < 0) {
350+
return NULL;
351+
}
352+
Py_RETURN_NONE;
353+
}
354+
355+
335356
static PyObject*
336357
writer_write_widechar(PyObject *self_raw, PyObject *args)
337358
{
@@ -513,6 +534,7 @@ writer_finish(PyObject *self_raw, PyObject *Py_UNUSED(args))
513534
static PyMethodDef writer_methods[] = {
514535
{"write_char", _PyCFunction_CAST(writer_write_char), METH_VARARGS},
515536
{"write_utf8", _PyCFunction_CAST(writer_write_utf8), METH_VARARGS},
537+
{"write_ascii", _PyCFunction_CAST(writer_write_ascii), METH_VARARGS},
516538
{"write_widechar", _PyCFunction_CAST(writer_write_widechar), METH_VARARGS},
517539
{"write_ucs4", _PyCFunction_CAST(writer_write_ucs4), METH_VARARGS},
518540
{"write_str", _PyCFunction_CAST(writer_write_str), METH_VARARGS},

Objects/genericaliasobject.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ ga_repr_items_list(PyUnicodeWriter *writer, PyObject *p)
6565

6666
for (Py_ssize_t i = 0; i < len; i++) {
6767
if (i > 0) {
68-
if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
68+
if (PyUnicodeWriter_WriteASCII(writer, ", ", 2) < 0) {
6969
return -1;
7070
}
7171
}
@@ -109,7 +109,7 @@ ga_repr(PyObject *self)
109109
}
110110
for (Py_ssize_t i = 0; i < len; i++) {
111111
if (i > 0) {
112-
if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) {
112+
if (PyUnicodeWriter_WriteASCII(writer, ", ", 2) < 0) {
113113
goto error;
114114
}
115115
}
@@ -126,7 +126,7 @@ ga_repr(PyObject *self)
126126
}
127127
if (len == 0) {
128128
/ for something like tuple[()] we should print a "()"
129-
if (PyUnicodeWriter_WriteUTF8(writer, "()", 2) < 0) {
129+
if (PyUnicodeWriter_WriteASCII(writer, "()", 2) < 0) {
130130
goto error;
131131
}
132132
}

0 commit comments

Comments
 (0)

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant