From 2c789a9db9b6fba42722fb0c179d654a387950d1 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 2 Apr 2024 21:06:08 +0200 Subject: [PATCH 01/10] Adapt byte*.startswith --- Objects/bytearrayobject.c | 20 ++++++++++++--- Objects/bytes_methods.c | 8 ------ Objects/bytesobject.c | 20 ++++++++++++--- Objects/clinic/bytearrayobject.c.h | 41 +++++++++++++++++++++++++++++- Objects/clinic/bytesobject.c.h | 41 +++++++++++++++++++++++++++++- 5 files changed, 114 insertions(+), 16 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 5e3b3affbc76c5..48a6eb018befec 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1186,8 +1186,23 @@ bytearray_contains(PyObject *self, PyObject *arg) return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytearray.startswith + + *args: object + / + +Return True if B starts with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytearray_startswith(PyByteArrayObject *self, PyObject *args) +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=cfec6eb4d8d465b2 input=53a7036eaff0525e]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } @@ -2249,8 +2264,7 @@ bytearray_methods[] = { BYTEARRAY_RSTRIP_METHODDEF BYTEARRAY_SPLIT_METHODDEF BYTEARRAY_SPLITLINES_METHODDEF - {"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS , - _Py_startswith__doc__}, + BYTEARRAY_STARTSWITH_METHODDEF BYTEARRAY_STRIP_METHODDEF {"swapcase", stringlib_swapcase, METH_NOARGS, _Py_swapcase__doc__}, diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index c1bc6383df30ce..a18a2aaa332688 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -807,14 +807,6 @@ _Py_bytes_tailmatch(const char *str, Py_ssize_t len, return PyBool_FromLong(result); } -PyDoc_STRVAR_shared(_Py_startswith__doc__, -"B.startswith(prefix[, start[, end]]) -> bool\n\ -\n\ -Return True if B starts with the specified prefix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -prefix can also be a tuple of bytes to try."); - PyObject * _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) { diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 256e01f54f0782..5836ad9a628829 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2285,8 +2285,23 @@ bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix) return PyBytes_FromStringAndSize(self_start, self_len); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytes.startswith + + *args: object + / + +Return True if B starts with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytes_startswith(PyBytesObject *self, PyObject *args) +bytes_startswith_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=172340dafc2f3c97 input=87559404108dcdfc]*/ { return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } @@ -2532,8 +2547,7 @@ bytes_methods[] = { BYTES_RSTRIP_METHODDEF BYTES_SPLIT_METHODDEF BYTES_SPLITLINES_METHODDEF - {"startswith", (PyCFunction)bytes_startswith, METH_VARARGS, - _Py_startswith__doc__}, + BYTES_STARTSWITH_METHODDEF BYTES_STRIP_METHODDEF {"swapcase", stringlib_swapcase, METH_NOARGS, _Py_swapcase__doc__}, diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index d95245067e2608..5ede27b998136d 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -137,6 +137,45 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) return bytearray_copy_impl(self); } +PyDoc_STRVAR(bytearray_startswith__doc__, +"startswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B starts with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTEARRAY_STARTSWITH_METHODDEF \ + {"startswith", _PyCFunction_CAST(bytearray_startswith), METH_FASTCALL, bytearray_startswith__doc__}, + +static PyObject * +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_startswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytearray_removeprefix__doc__, "removeprefix($self, prefix, /)\n" "--\n" @@ -1261,4 +1300,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=0797a5e03cda2a16 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=01c78d65700f652d input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 1e45be3e7aefb3..e4b7211382035d 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -652,6 +652,45 @@ bytes_removesuffix(PyBytesObject *self, PyObject *arg) return return_value; } +PyDoc_STRVAR(bytes_startswith__doc__, +"startswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B starts with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTES_STARTSWITH_METHODDEF \ + {"startswith", _PyCFunction_CAST(bytes_startswith), METH_FASTCALL, bytes_startswith__doc__}, + +static PyObject * +bytes_startswith_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_startswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytes_decode__doc__, "decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" @@ -1029,4 +1068,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=8a49dbbd78914a6f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9148bed58e358e53 input=a9049054013a1b77]*/ From 132080c20e9cfadc64f2b650e93c33e7cb9862bf Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 2 Apr 2024 21:30:28 +0200 Subject: [PATCH 02/10] Adapt byte*.endswith --- Objects/bytearrayobject.c | 17 ++++++++++--- Objects/bytes_methods.c | 8 ------ Objects/bytesobject.c | 17 ++++++++++--- Objects/clinic/bytearrayobject.c.h | 41 +++++++++++++++++++++++++++++- Objects/clinic/bytesobject.c.h | 41 +++++++++++++++++++++++++++++- 5 files changed, 108 insertions(+), 16 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 48a6eb018befec..dc173d58cbf7b5 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1207,8 +1207,20 @@ bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args) return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytearray.endswith = bytearray.startswith + +Return True if B ends with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytearray_endswith(PyByteArrayObject *self, PyObject *args) +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args) +/*[clinic end generated code: output=2d9b7e94ef2b142a input=2a2ba6955504ae08]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); } @@ -2218,8 +2230,7 @@ bytearray_methods[] = { {"count", (PyCFunction)bytearray_count, METH_VARARGS, _Py_count__doc__}, BYTEARRAY_DECODE_METHODDEF - {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS, - _Py_endswith__doc__}, + BYTEARRAY_ENDSWITH_METHODDEF STRINGLIB_EXPANDTABS_METHODDEF BYTEARRAY_EXTEND_METHODDEF {"find", (PyCFunction)bytearray_find, METH_VARARGS, diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index a18a2aaa332688..4a778ef4a82b22 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -813,14 +813,6 @@ _Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) return _Py_bytes_tailmatch(str, len, "startswith", args, -1); } -PyDoc_STRVAR_shared(_Py_endswith__doc__, -"B.endswith(suffix[, start[, end]]) -> bool\n\ -\n\ -Return True if B ends with the specified suffix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -suffix can also be a tuple of bytes to try."); - PyObject * _Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) { diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 5836ad9a628829..b105995e6168fa 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2306,8 +2306,20 @@ bytes_startswith_impl(PyBytesObject *self, PyObject *args) return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } +/*[clinic input] +@text_signature "($self, prefix[, start[, end]], /)" +bytes.endswith = bytes.startswith + +Return True if B ends with the specified prefix, False otherwise. + +With optional start, test B beginning at that position. +With optional end, stop comparing B at that position. +prefix can also be a tuple of bytes to try. +[clinic start generated code]*/ + static PyObject * -bytes_endswith(PyBytesObject *self, PyObject *args) +bytes_endswith_impl(PyBytesObject *self, PyObject *args) +/*[clinic end generated code: output=b462e732a996e3eb input=3f7fc635440e2ab5]*/ { return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); } @@ -2506,8 +2518,7 @@ bytes_methods[] = { {"count", (PyCFunction)bytes_count, METH_VARARGS, _Py_count__doc__}, BYTES_DECODE_METHODDEF - {"endswith", (PyCFunction)bytes_endswith, METH_VARARGS, - _Py_endswith__doc__}, + BYTES_ENDSWITH_METHODDEF STRINGLIB_EXPANDTABS_METHODDEF {"find", (PyCFunction)bytes_find, METH_VARARGS, _Py_find__doc__}, diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 5ede27b998136d..addef9c995c51a 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -176,6 +176,45 @@ bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t return return_value; } +PyDoc_STRVAR(bytearray_endswith__doc__, +"endswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B ends with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTEARRAY_ENDSWITH_METHODDEF \ + {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, + +static PyObject * +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args); + +static PyObject * +bytearray_endswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytearray_endswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytearray_removeprefix__doc__, "removeprefix($self, prefix, /)\n" "--\n" @@ -1300,4 +1339,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=01c78d65700f652d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0074ca263a60fd85 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index e4b7211382035d..054ffb572ab780 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -691,6 +691,45 @@ bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) return return_value; } +PyDoc_STRVAR(bytes_endswith__doc__, +"endswith($self, prefix[, start[, end]], /)\n" +"--\n" +"\n" +"Return True if B ends with the specified prefix, False otherwise.\n" +"\n" +"With optional start, test B beginning at that position.\n" +"With optional end, stop comparing B at that position.\n" +"prefix can also be a tuple of bytes to try."); + +#define BYTES_ENDSWITH_METHODDEF \ + {"endswith", _PyCFunction_CAST(bytes_endswith), METH_FASTCALL, bytes_endswith__doc__}, + +static PyObject * +bytes_endswith_impl(PyBytesObject *self, PyObject *args); + +static PyObject * +bytes_endswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *__clinic_args = NULL; + + if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + goto exit; + } + __clinic_args = PyTuple_New(nargs - 0); + if (!__clinic_args) { + goto exit; + } + for (Py_ssize_t i = 0; i < nargs - 0; ++i) { + PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + } + return_value = bytes_endswith_impl(self, __clinic_args); + +exit: + Py_XDECREF(__clinic_args); + return return_value; +} + PyDoc_STRVAR(bytes_decode__doc__, "decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" @@ -1068,4 +1107,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=9148bed58e358e53 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ec9b14dc1196888d input=a9049054013a1b77]*/ From b7f04d7d9cd3d0a83556eb2117142a06774bc08d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Tue, 2 Apr 2024 21:49:17 +0200 Subject: [PATCH 03/10] Optimise --- Include/internal/pycore_bytes_methods.h | 8 ++- Objects/bytearrayobject.c | 27 ++++++--- Objects/bytes_methods.c | 35 +++++------ Objects/bytesobject.c | 35 +++++------ Objects/clinic/bytearrayobject.c.h | 74 ++++++++++++++++------- Objects/clinic/bytesobject.c.h | 78 ++++++++++++++++--------- 6 files changed, 162 insertions(+), 95 deletions(-) diff --git a/Include/internal/pycore_bytes_methods.h b/Include/internal/pycore_bytes_methods.h index 11e8ab20e91367..b9c0a4e2b2f77d 100644 --- a/Include/internal/pycore_bytes_methods.h +++ b/Include/internal/pycore_bytes_methods.h @@ -32,8 +32,12 @@ extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args); extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args); extern int _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg); -extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args); -extern PyObject *_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len, + PyObject *subobj, Py_ssize_t start, + Py_ssize_t end); +extern PyObject *_Py_bytes_endswith(const char *str, Py_ssize_t len, + PyObject *subobj, Py_ssize_t start, + Py_ssize_t end); /* The maketrans() static method. */ extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to); diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index dc173d58cbf7b5..8d6e91998288fe 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1190,10 +1190,15 @@ bytearray_contains(PyObject *self, PyObject *arg) @text_signature "($self, prefix[, start[, end]], /)" bytearray.startswith - *args: object + prefix as subobj: object + A byte string or a tuple of byte strings to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the byte string. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the byte string. / -Return True if B starts with the specified prefix, False otherwise. +Return True if the byte string starts with the specified prefix, False otherwise. With optional start, test B beginning at that position. With optional end, stop comparing B at that position. @@ -1201,17 +1206,19 @@ prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * -bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=cfec6eb4d8d465b2 input=53a7036eaff0525e]*/ +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=596f48473d404176]*/ { - return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + subobj, start, end); } /*[clinic input] @text_signature "($self, prefix[, start[, end]], /)" bytearray.endswith = bytearray.startswith -Return True if B ends with the specified prefix, False otherwise. +Return True if the byte string ends with the specified prefix, False otherwise. With optional start, test B beginning at that position. With optional end, stop comparing B at that position. @@ -1219,10 +1226,12 @@ prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * -bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args) -/*[clinic end generated code: output=2d9b7e94ef2b142a input=2a2ba6955504ae08]*/ +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=e75ea8c227954caa input=96d3f21baa53c7b2]*/ { - return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args); + return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), + subobj, start, end); } /*[clinic input] diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index 4a778ef4a82b22..21b6668171bf61 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -771,50 +771,47 @@ tailmatch(const char *str, Py_ssize_t len, PyObject *substr, static PyObject * _Py_bytes_tailmatch(const char *str, Py_ssize_t len, - const char *function_name, PyObject *args, + const char *function_name, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end, int direction) { - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - PyObject *subobj = NULL; - int result; - - if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end)) - return NULL; if (PyTuple_Check(subobj)) { Py_ssize_t i; for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i), - start, end, direction); - if (result == -1) + PyObject *item = PyTuple_GET_ITEM(subobj, i); + int result = tailmatch(str, len, item, start, end, direction); + if (result < 0) { return NULL; + } else if (result) { Py_RETURN_TRUE; } } Py_RETURN_FALSE; } - result = tailmatch(str, len, subobj, start, end, direction); + int result = tailmatch(str, len, subobj, start, end, direction); if (result == -1) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) + if (PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Format(PyExc_TypeError, "%s first arg must be bytes or a tuple of bytes, " "not %s", function_name, Py_TYPE(subobj)->tp_name); + } return NULL; } - else - return PyBool_FromLong(result); + return PyBool_FromLong(result); } PyObject * -_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) { - return _Py_bytes_tailmatch(str, len, "startswith", args, -1); + return _Py_bytes_tailmatch(str, len, "startswith", subobj, start, end, -1); } PyObject * -_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args) +_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) { - return _Py_bytes_tailmatch(str, len, "endswith", args, +1); + return _Py_bytes_tailmatch(str, len, "endswith", subobj, start, end, +1); } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index b105995e6168fa..141d01e795787b 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2289,39 +2289,40 @@ bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix) @text_signature "($self, prefix[, start[, end]], /)" bytes.startswith - *args: object + prefix as subobj: object + A byte string or a tuple of byte strings to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the byte string. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the byte string. / -Return True if B starts with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. +Return True if the byte string starts with the specified prefix, False otherwise. [clinic start generated code]*/ static PyObject * -bytes_startswith_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=172340dafc2f3c97 input=87559404108dcdfc]*/ +bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end) +/*[clinic end generated code: output=b1e8da1cbd528e8c input=86b5f991fc8ac0dc]*/ { - return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + subobj, start, end); } /*[clinic input] @text_signature "($self, prefix[, start[, end]], /)" bytes.endswith = bytes.startswith -Return True if B ends with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. +Return True if the byte string ends with the specified prefix, False otherwise. [clinic start generated code]*/ static PyObject * -bytes_endswith_impl(PyBytesObject *self, PyObject *args) -/*[clinic end generated code: output=b462e732a996e3eb input=3f7fc635440e2ab5]*/ +bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, + Py_ssize_t end) +/*[clinic end generated code: output=038b633111f3629d input=38d3f36990facc7b]*/ { - return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args); + return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), + subobj, start, end); } diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index addef9c995c51a..a161a1a485666b 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -141,7 +141,14 @@ PyDoc_STRVAR(bytearray_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B starts with the specified prefix, False otherwise.\n" +"Return True if the byte string starts with the specified prefix, False otherwise.\n" +"\n" +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string.\n" "\n" "With optional start, test B beginning at that position.\n" "With optional end, stop comparing B at that position.\n" @@ -151,28 +158,37 @@ PyDoc_STRVAR(bytearray_startswith__doc__, {"startswith", _PyCFunction_CAST(bytearray_startswith), METH_FASTCALL, bytearray_startswith__doc__}, static PyObject * -bytearray_startswith_impl(PyByteArrayObject *self, PyObject *args); +bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("startswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytearray_startswith_impl(self, __clinic_args); +skip_optional: + return_value = bytearray_startswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -180,7 +196,14 @@ PyDoc_STRVAR(bytearray_endswith__doc__, "endswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified prefix, False otherwise.\n" +"\n" +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string.\n" "\n" "With optional start, test B beginning at that position.\n" "With optional end, stop comparing B at that position.\n" @@ -190,28 +213,37 @@ PyDoc_STRVAR(bytearray_endswith__doc__, {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, static PyObject * -bytearray_endswith_impl(PyByteArrayObject *self, PyObject *args); +bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytearray_endswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("endswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; } - return_value = bytearray_endswith_impl(self, __clinic_args); +skip_optional: + return_value = bytearray_endswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -1339,4 +1371,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=0074ca263a60fd85 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8ef9bb3a7401c0f6 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 054ffb572ab780..ed31ec7a2876ed 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -656,38 +656,50 @@ PyDoc_STRVAR(bytes_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B starts with the specified prefix, False otherwise.\n" +"Return True if the byte string starts with the specified prefix, False otherwise.\n" "\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string."); #define BYTES_STARTSWITH_METHODDEF \ {"startswith", _PyCFunction_CAST(bytes_startswith), METH_FASTCALL, bytes_startswith__doc__}, static PyObject * -bytes_startswith_impl(PyBytesObject *self, PyObject *args); +bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, + Py_ssize_t start, Py_ssize_t end); static PyObject * bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("startswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("startswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; } - return_value = bytes_startswith_impl(self, __clinic_args); + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; + } +skip_optional: + return_value = bytes_startswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -695,38 +707,50 @@ PyDoc_STRVAR(bytes_endswith__doc__, "endswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if B ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified prefix, False otherwise.\n" "\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" prefix\n" +" A byte string or a tuple of byte strings to try.\n" +" start\n" +" Optional start position. Default: start of the byte string.\n" +" end\n" +" Optional stop position. Default: end of the byte string."); #define BYTES_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytes_endswith), METH_FASTCALL, bytes_endswith__doc__}, static PyObject * -bytes_endswith_impl(PyBytesObject *self, PyObject *args); +bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, + Py_ssize_t end); static PyObject * bytes_endswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *__clinic_args = NULL; + PyObject *subobj; + Py_ssize_t start = 0; + Py_ssize_t end = PY_SSIZE_T_MAX; - if (!_PyArg_CheckPositional("endswith", nargs, 0, PY_SSIZE_T_MAX)) { + if (!_PyArg_CheckPositional("endswith", nargs, 1, 3)) { goto exit; } - __clinic_args = PyTuple_New(nargs - 0); - if (!__clinic_args) { + subobj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[1], &start)) { goto exit; } - for (Py_ssize_t i = 0; i < nargs - 0; ++i) { - PyTuple_SET_ITEM(__clinic_args, i, Py_NewRef(args[0 + i])); + if (nargs < 3) { + goto skip_optional; } - return_value = bytes_endswith_impl(self, __clinic_args); + if (!_PyEval_SliceIndex(args[2], &end)) { + goto exit; + } +skip_optional: + return_value = bytes_endswith_impl(self, subobj, start, end); exit: - Py_XDECREF(__clinic_args); return return_value; } @@ -1107,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=ec9b14dc1196888d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4c2cdae78ce05ce5 input=a9049054013a1b77]*/ From 57c9afcc2eaebc8b2751413e14fd3478b425c7e8 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:49:20 +0200 Subject: [PATCH 04/10] Add NEWS --- .../2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst new file mode 100644 index 00000000000000..17374d0d5c575b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-03-09-49-15.gh-issue-117431.WAqRgc.rst @@ -0,0 +1,6 @@ +Improve the performance of the following :class:`bytes` and +:class:`bytearray` methods by adapting them to the :c:macro:`METH_FASTCALL` +calling convention: + +* :meth:`!endswith` +* :meth:`!startswith` From 1b89eb9c8c7669fc1daeb22842ce9bebcdaccc09 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:54:26 +0200 Subject: [PATCH 05/10] Adjust docstring --- Objects/bytearrayobject.c | 6 +----- Objects/clinic/bytearrayobject.c.h | 8 ++------ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 8d6e91998288fe..5b07f23fdb76c0 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1219,16 +1219,12 @@ bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, bytearray.endswith = bytearray.startswith Return True if the byte string ends with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=e75ea8c227954caa input=96d3f21baa53c7b2]*/ +/*[clinic end generated code: output=e75ea8c227954caa input=6b8a65e1d0071201]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index a161a1a485666b..aa923ab23609ed 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -203,11 +203,7 @@ PyDoc_STRVAR(bytearray_endswith__doc__, " start\n" " Optional start position. Default: start of the byte string.\n" " end\n" -" Optional stop position. Default: end of the byte string.\n" -"\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" Optional stop position. Default: end of the byte string."); #define BYTEARRAY_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, @@ -1371,4 +1367,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=8ef9bb3a7401c0f6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=11cc701b1df6250e input=a9049054013a1b77]*/ From fabe7618c5b762687093d1984a211ce25639e131 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:57:21 +0200 Subject: [PATCH 06/10] Docstring: Use 'bytes' or 'bytearray' instead of 'byte string' --- Objects/bytearrayobject.c | 10 +++++----- Objects/bytesobject.c | 10 +++++----- Objects/clinic/bytearrayobject.c.h | 16 ++++++++-------- Objects/clinic/bytesobject.c.h | 16 ++++++++-------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 5b07f23fdb76c0..329bea92472994 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1191,14 +1191,14 @@ bytearray_contains(PyObject *self, PyObject *arg) bytearray.startswith prefix as subobj: object - A byte string or a tuple of byte strings to try. + A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the byte string. + Optional start position. Default: start of the bytearray. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the byte string. + Optional stop position. Default: end of the bytearray. / -Return True if the byte string starts with the specified prefix, False otherwise. +Return True if the bytearray starts with the specified prefix, False otherwise. With optional start, test B beginning at that position. With optional end, stop comparing B at that position. @@ -1208,7 +1208,7 @@ prefix can also be a tuple of bytes to try. static PyObject * bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=a3d9b6d44d3662a6 input=596f48473d404176]*/ +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=1bb77e6e964116b5]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 141d01e795787b..0a62f40f0a6571 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2290,20 +2290,20 @@ bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix) bytes.startswith prefix as subobj: object - A byte string or a tuple of byte strings to try. + A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the byte string. + Optional start position. Default: start of the bytes. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the byte string. + Optional stop position. Default: end of the bytes. / -Return True if the byte string starts with the specified prefix, False otherwise. +Return True if the bytes starts with the specified prefix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=b1e8da1cbd528e8c input=86b5f991fc8ac0dc]*/ +/*[clinic end generated code: output=b1e8da1cbd528e8c input=917d9cf26c33b96a]*/ { return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index aa923ab23609ed..eceffcbb47154a 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -141,14 +141,14 @@ PyDoc_STRVAR(bytearray_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string starts with the specified prefix, False otherwise.\n" +"Return True if the bytearray starts with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytearray.\n" " end\n" -" Optional stop position. Default: end of the byte string.\n" +" Optional stop position. Default: end of the bytearray.\n" "\n" "With optional start, test B beginning at that position.\n" "With optional end, stop comparing B at that position.\n" @@ -199,11 +199,11 @@ PyDoc_STRVAR(bytearray_endswith__doc__, "Return True if the byte string ends with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytearray.\n" " end\n" -" Optional stop position. Default: end of the byte string."); +" Optional stop position. Default: end of the bytearray."); #define BYTEARRAY_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytearray_endswith), METH_FASTCALL, bytearray_endswith__doc__}, @@ -1367,4 +1367,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=11cc701b1df6250e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d1ec3d7be5d1093c input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index ed31ec7a2876ed..4571d5d9314172 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -656,14 +656,14 @@ PyDoc_STRVAR(bytes_startswith__doc__, "startswith($self, prefix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string starts with the specified prefix, False otherwise.\n" +"Return True if the bytes starts with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytes.\n" " end\n" -" Optional stop position. Default: end of the byte string."); +" Optional stop position. Default: end of the bytes."); #define BYTES_STARTSWITH_METHODDEF \ {"startswith", _PyCFunction_CAST(bytes_startswith), METH_FASTCALL, bytes_startswith__doc__}, @@ -710,11 +710,11 @@ PyDoc_STRVAR(bytes_endswith__doc__, "Return True if the byte string ends with the specified prefix, False otherwise.\n" "\n" " prefix\n" -" A byte string or a tuple of byte strings to try.\n" +" A bytes or a tuple of bytes to try.\n" " start\n" -" Optional start position. Default: start of the byte string.\n" +" Optional start position. Default: start of the bytes.\n" " end\n" -" Optional stop position. Default: end of the byte string."); +" Optional stop position. Default: end of the bytes."); #define BYTES_ENDSWITH_METHODDEF \ {"endswith", _PyCFunction_CAST(bytes_endswith), METH_FASTCALL, bytes_endswith__doc__}, @@ -1131,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=4c2cdae78ce05ce5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5d319f11a99fbc02 input=a9049054013a1b77]*/ From e9b59cc5ddcb06d331682943cc3b67974d7907ea Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 09:58:30 +0200 Subject: [PATCH 07/10] Docstring: Remove unneeded body from bytearray.startswith; the param section will fill in the needed info --- Objects/bytearrayobject.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 329bea92472994..c82c8edee35fc6 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1199,10 +1199,6 @@ bytearray.startswith / Return True if the bytearray starts with the specified prefix, False otherwise. - -With optional start, test B beginning at that position. -With optional end, stop comparing B at that position. -prefix can also be a tuple of bytes to try. [clinic start generated code]*/ static PyObject * From 655a6a88fed9035838e9fe389766024f22568c29 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 10:08:37 +0200 Subject: [PATCH 08/10] Regen clinic --- Objects/bytearrayobject.c | 2 +- Objects/clinic/bytearrayobject.c.h | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index c82c8edee35fc6..6055852fd44ef0 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1204,7 +1204,7 @@ Return True if the bytearray starts with the specified prefix, False otherwise. static PyObject * bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=a3d9b6d44d3662a6 input=1bb77e6e964116b5]*/ +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=5815c1138cf1ba28]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index eceffcbb47154a..5ae2964fed944a 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -148,11 +148,7 @@ PyDoc_STRVAR(bytearray_startswith__doc__, " start\n" " Optional start position. Default: start of the bytearray.\n" " end\n" -" Optional stop position. Default: end of the bytearray.\n" -"\n" -"With optional start, test B beginning at that position.\n" -"With optional end, stop comparing B at that position.\n" -"prefix can also be a tuple of bytes to try."); +" Optional stop position. Default: end of the bytearray."); #define BYTEARRAY_STARTSWITH_METHODDEF \ {"startswith", _PyCFunction_CAST(bytearray_startswith), METH_FASTCALL, bytearray_startswith__doc__}, @@ -1367,4 +1363,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=d1ec3d7be5d1093c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=353628ec8834ad01 input=a9049054013a1b77]*/ From 2c54b79ab333a05fe0c6e297e54b505a05ffc268 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 11:55:44 +0200 Subject: [PATCH 09/10] Address Inada-san's review: endswith's first param is named 'suffix' --- Objects/bytearrayobject.c | 16 ++++++++++++---- Objects/bytesobject.c | 16 ++++++++++++---- Objects/clinic/bytearrayobject.c.h | 8 ++++---- Objects/clinic/bytesobject.c.h | 8 ++++---- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 6055852fd44ef0..e9763dfe338fe2 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1211,16 +1211,24 @@ bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, } /*[clinic input] -@text_signature "($self, prefix[, start[, end]], /)" -bytearray.endswith = bytearray.startswith +@text_signature "($self, suffix[, start[, end]], /)" +bytearray.endswith + + suffix as subobj: object + A bytes or a tuple of bytes to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the bytearray. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the bytearray. + / -Return True if the byte string ends with the specified prefix, False otherwise. +Return True if the byte string ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=e75ea8c227954caa input=6b8a65e1d0071201]*/ +/*[clinic end generated code: output=e75ea8c227954caa input=3b63c2dc878407c2]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 0a62f40f0a6571..33e3fc3da41e16 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2310,16 +2310,24 @@ bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, } /*[clinic input] -@text_signature "($self, prefix[, start[, end]], /)" -bytes.endswith = bytes.startswith +@text_signature "($self, suffix[, start[, end]], /)" +bytes.endswith + + suffix as subobj: object + A bytes or a tuple of bytes to try. + start: slice_index(accept={int, NoneType}, c_default='0') = None + Optional start position. Default: start of the bytes. + end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None + Optional stop position. Default: end of the bytes. + / -Return True if the byte string ends with the specified prefix, False otherwise. +Return True if the byte string ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=038b633111f3629d input=38d3f36990facc7b]*/ +/*[clinic end generated code: output=038b633111f3629d input=66b64eccac830889]*/ { return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index 5ae2964fed944a..b4743ad8cad947 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -189,12 +189,12 @@ bytearray_startswith(PyByteArrayObject *self, PyObject *const *args, Py_ssize_t } PyDoc_STRVAR(bytearray_endswith__doc__, -"endswith($self, prefix[, start[, end]], /)\n" +"endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified suffix, False otherwise.\n" "\n" -" prefix\n" +" suffix\n" " A bytes or a tuple of bytes to try.\n" " start\n" " Optional start position. Default: start of the bytearray.\n" @@ -1363,4 +1363,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=353628ec8834ad01 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4264a5341cb44fef input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 4571d5d9314172..944b882e01472d 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -704,12 +704,12 @@ bytes_startswith(PyBytesObject *self, PyObject *const *args, Py_ssize_t nargs) } PyDoc_STRVAR(bytes_endswith__doc__, -"endswith($self, prefix[, start[, end]], /)\n" +"endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified prefix, False otherwise.\n" +"Return True if the byte string ends with the specified suffix, False otherwise.\n" "\n" -" prefix\n" +" suffix\n" " A bytes or a tuple of bytes to try.\n" " start\n" " Optional start position. Default: start of the bytes.\n" @@ -1131,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=5d319f11a99fbc02 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=48f0667452337301 input=a9049054013a1b77]*/ From 2443309e1baf0eceb5e52b2d7c172dc72dfed739 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 3 Apr 2024 12:23:50 +0200 Subject: [PATCH 10/10] Address Inada-san's review: indent clinic input and consistently use 'the bytes' and 'the bytearray' in docstring --- Objects/bytearrayobject.c | 10 +++++----- Objects/bytesobject.c | 10 +++++----- Objects/clinic/bytearrayobject.c.h | 4 ++-- Objects/clinic/bytesobject.c.h | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index e9763dfe338fe2..8639496727536a 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1193,9 +1193,9 @@ bytearray.startswith prefix as subobj: object A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the bytearray. + Optional start position. Default: start of the bytearray. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the bytearray. + Optional stop position. Default: end of the bytearray. / Return True if the bytearray starts with the specified prefix, False otherwise. @@ -1204,7 +1204,7 @@ Return True if the bytearray starts with the specified prefix, False otherwise. static PyObject * bytearray_startswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=a3d9b6d44d3662a6 input=5815c1138cf1ba28]*/ +/*[clinic end generated code: output=a3d9b6d44d3662a6 input=76385e0b376b45c1]*/ { return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); @@ -1222,13 +1222,13 @@ bytearray.endswith Optional stop position. Default: end of the bytearray. / -Return True if the byte string ends with the specified suffix, False otherwise. +Return True if the bytearray ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytearray_endswith_impl(PyByteArrayObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=e75ea8c227954caa input=3b63c2dc878407c2]*/ +/*[clinic end generated code: output=e75ea8c227954caa input=9b8baa879aa3d74b]*/ { return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subobj, start, end); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 33e3fc3da41e16..d7b0c6b7b01aa9 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2292,9 +2292,9 @@ bytes.startswith prefix as subobj: object A bytes or a tuple of bytes to try. start: slice_index(accept={int, NoneType}, c_default='0') = None - Optional start position. Default: start of the bytes. + Optional start position. Default: start of the bytes. end: slice_index(accept={int, NoneType}, c_default='PY_SSIZE_T_MAX') = None - Optional stop position. Default: end of the bytes. + Optional stop position. Default: end of the bytes. / Return True if the bytes starts with the specified prefix, False otherwise. @@ -2303,7 +2303,7 @@ Return True if the bytes starts with the specified prefix, False otherwise. static PyObject * bytes_startswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=b1e8da1cbd528e8c input=917d9cf26c33b96a]*/ +/*[clinic end generated code: output=b1e8da1cbd528e8c input=8a4165df8adfa6c9]*/ { return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); @@ -2321,13 +2321,13 @@ bytes.endswith Optional stop position. Default: end of the bytes. / -Return True if the byte string ends with the specified suffix, False otherwise. +Return True if the bytes ends with the specified suffix, False otherwise. [clinic start generated code]*/ static PyObject * bytes_endswith_impl(PyBytesObject *self, PyObject *subobj, Py_ssize_t start, Py_ssize_t end) -/*[clinic end generated code: output=038b633111f3629d input=66b64eccac830889]*/ +/*[clinic end generated code: output=038b633111f3629d input=b5c3407a2a5c9aac]*/ { return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), subobj, start, end); diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h index b4743ad8cad947..dabc2b16c94fce 100644 --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -192,7 +192,7 @@ PyDoc_STRVAR(bytearray_endswith__doc__, "endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified suffix, False otherwise.\n" +"Return True if the bytearray ends with the specified suffix, False otherwise.\n" "\n" " suffix\n" " A bytes or a tuple of bytes to try.\n" @@ -1363,4 +1363,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=4264a5341cb44fef input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0147908e97ebe882 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h index 944b882e01472d..05e182778aece1 100644 --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -707,7 +707,7 @@ PyDoc_STRVAR(bytes_endswith__doc__, "endswith($self, suffix[, start[, end]], /)\n" "--\n" "\n" -"Return True if the byte string ends with the specified suffix, False otherwise.\n" +"Return True if the bytes ends with the specified suffix, False otherwise.\n" "\n" " suffix\n" " A bytes or a tuple of bytes to try.\n" @@ -1131,4 +1131,4 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=48f0667452337301 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f2b10ccd2e3155c3 input=a9049054013a1b77]*/