diff --git a/Include/internal/pycore_bytes_methods.h b/Include/internal/pycore_bytes_methods.h index 3e1474c1c010f9..02bd8c53c1e126 100644 --- a/Include/internal/pycore_bytes_methods.h +++ b/Include/internal/pycore_bytes_methods.h @@ -29,11 +29,13 @@ extern void _Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len); extern PyObject *_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *sub, Py_ssize_t start, Py_ssize_t end); extern PyObject *_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *sub, - Py_ssize_t start, Py_ssize_t end); + Py_ssize_t start, Py_ssize_t end, + const char *classname); extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *sub, Py_ssize_t start, Py_ssize_t end); extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *sub, - Py_ssize_t start, Py_ssize_t end); + Py_ssize_t start, Py_ssize_t end, + const char *classname); extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *sub, Py_ssize_t start, Py_ssize_t end); extern int _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg); diff --git a/Lib/operator.py b/Lib/operator.py index 1b765522f85949..9268ef35e7ea9a 100644 --- a/Lib/operator.py +++ b/Lib/operator.py @@ -184,7 +184,7 @@ def indexOf(a, b): if j is b or j == b: return i else: - raise ValueError('sequence.index(x): x not in sequence') + raise ValueError('value not in sequence') def setitem(a, b, c): "Same as a[b] = c." diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-07-18-20-33.gh-issue-137508.Llt4Ei.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-07-18-20-33.gh-issue-137508.Llt4Ei.rst new file mode 100644 index 00000000000000..5458b17ffd941d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-07-18-20-33.gh-issue-137508.Llt4Ei.rst @@ -0,0 +1,5 @@ +Unify error messages for the :meth:`!index` and :meth:`!remove` methods of +classes :class:`list`, :class:`tuple`, :class:`range`, :class:`memoryview`, +:class:`str`, :class:`bytes`, :class:`bytearray`, :class:`array.array`, and +:class:`collections.deque`, and the :func:`operator.indexOf` function. +Improve error message for :meth:`xml.etree.ElementTree.Element.remove`. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 4ff05727ebc8ce..6254d046da0319 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1318,7 +1318,7 @@ deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start, index = 0; } } - PyErr_SetString(PyExc_ValueError, "deque.index(x): x not in deque"); + PyErr_SetString(PyExc_ValueError, "value not in deque"); return NULL; } @@ -1488,7 +1488,7 @@ deque_remove_impl(dequeobject *deque, PyObject *value) } } if (i == n) { - PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque"); + PyErr_SetString(PyExc_ValueError, "value not in deque"); return NULL; } rv = deque_del_item(deque, i); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index a8347123e6496a..bdc752f6161130 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1396,7 +1396,7 @@ array_array_index_impl(arrayobject *self, PyObject *v, Py_ssize_t start, else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "array.index(x): x not in array"); + PyErr_SetString(PyExc_ValueError, "value not in array"); return NULL; } @@ -1448,7 +1448,7 @@ array_array_remove_impl(arrayobject *self, PyObject *v) else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "array.remove(x): x not in array"); + PyErr_SetString(PyExc_ValueError, "value not in array"); return NULL; } diff --git a/Objects/abstract.c b/Objects/abstract.c index 0bbf60840a3346..3636bd427a4abf 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2214,8 +2214,7 @@ _PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation) if (operation != PY_ITERSEARCH_INDEX) goto Done; - PyErr_SetString(PyExc_ValueError, - "sequence.index(x): x not in sequence"); + PyErr_SetString(PyExc_ValueError, "value not in sequence"); /* fall into failure code */ Fail: n = -1; diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index c583193b5a252c..81192570b15dcf 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -94,6 +94,10 @@ typedef PyObject* (*_ba_bytes_op)(const char *buf, Py_ssize_t len, PyObject *sub, Py_ssize_t start, Py_ssize_t end); +typedef PyObject* (*_ba_bytes_op2)(const char *buf, Py_ssize_t len, + PyObject *sub, Py_ssize_t start, + Py_ssize_t end, const char *classname); + static PyObject * _bytearray_with_buffer(PyByteArrayObject *self, _ba_bytes_op op, PyObject *sub, Py_ssize_t start, Py_ssize_t end) @@ -109,6 +113,22 @@ _bytearray_with_buffer(PyByteArrayObject *self, _ba_bytes_op op, PyObject *sub, return res; } +static PyObject * +_bytearray_with_buffer2(PyByteArrayObject *self, _ba_bytes_op2 op, PyObject *sub, + Py_ssize_t start, Py_ssize_t end) +{ + PyObject *res; + + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self); + + /* Increase exports to prevent bytearray storage from changing during op. */ + self->ob_exports++; + res = op(PyByteArray_AS_STRING(self), Py_SIZE(self), sub, start, end, + "bytearray"); + self->ob_exports--; + return res; +} + static int _canresize(PyByteArrayObject *self) { @@ -1331,7 +1351,7 @@ bytearray_index_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=067a1e78efc672a7 input=c37f177cfee19fe4]*/ { - return _bytearray_with_buffer(self, _Py_bytes_index, sub, start, end); + return _bytearray_with_buffer2(self, _Py_bytes_index, sub, start, end); } /*[clinic input] @@ -1367,7 +1387,7 @@ bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub, Py_ssize_t start, Py_ssize_t end) /*[clinic end generated code: output=38e1cf66bafb08b9 input=7d198b3d6b0a62ce]*/ { - return _bytearray_with_buffer(self, _Py_bytes_rindex, sub, start, end); + return _bytearray_with_buffer2(self, _Py_bytes_rindex, sub, start, end); } static int @@ -2336,7 +2356,7 @@ bytearray_remove_impl(PyByteArrayObject *self, int value) where = stringlib_find_char(buf, n, value); if (where < 0) { - PyErr_SetString(PyExc_ValueError, "value not found in bytearray"); + PyErr_SetString(PyExc_ValueError, "value not in bytearray"); return NULL; } if (!_canresize(self)) diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c index 56a461d0dd08a7..5c78c2cecab732 100644 --- a/Objects/bytes_methods.c +++ b/Objects/bytes_methods.c @@ -521,14 +521,18 @@ _Py_bytes_find(const char *str, Py_ssize_t len, PyObject *sub, PyObject * _Py_bytes_index(const char *str, Py_ssize_t len, PyObject *sub, - Py_ssize_t start, Py_ssize_t end) + Py_ssize_t start, Py_ssize_t end, const char *classname) { Py_ssize_t result = find_internal(str, len, "index", sub, start, end, +1); if (result == -2) return NULL; if (result == -1) { - PyErr_SetString(PyExc_ValueError, - "subsection not found"); + if (PyIndex_Check(sub)) { + PyErr_Format(PyExc_ValueError, "value not in %s", classname); + } + else { + PyErr_SetString(PyExc_ValueError, "subsection not found"); + } return NULL; } return PyLong_FromSsize_t(result); @@ -546,14 +550,15 @@ _Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *sub, PyObject * _Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *sub, - Py_ssize_t start, Py_ssize_t end) + Py_ssize_t start, Py_ssize_t end, const char *classname) { Py_ssize_t result = find_internal(str, len, "rindex", sub, start, end, -1); if (result == -2) return NULL; if (result == -1) { - PyErr_SetString(PyExc_ValueError, - "subsection not found"); + PyErr_Format(PyExc_ValueError, "%s not in %s", + PyIndex_Check(sub) ? "value" : "subsection", + classname); return NULL; } return PyLong_FromSsize_t(result); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 8a9d1b133affb3..db2f98fd617b09 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2052,7 +2052,7 @@ bytes_index_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, /*[clinic end generated code: output=0da25cc74683ba42 input=1cb45ce71456a269]*/ { return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sub, start, end); + sub, start, end, "bytes"); } /*[clinic input] @@ -2088,7 +2088,7 @@ bytes_rindex_impl(PyBytesObject *self, PyObject *sub, Py_ssize_t start, /*[clinic end generated code: output=42bf674e0a0aabf6 input=bb5f473c64610c43]*/ { return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sub, start, end); + sub, start, end, "bytes"); } diff --git a/Objects/listobject.c b/Objects/listobject.c index 10e25bbdcdcb6c..cc5d8cc9511188 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3350,7 +3350,7 @@ list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start, else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "list.index(x): x not in list"); + PyErr_SetString(PyExc_ValueError, "value not in list"); return NULL; } @@ -3420,7 +3420,7 @@ list_remove_impl(PyListObject *self, PyObject *value) else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list"); + PyErr_SetString(PyExc_ValueError, "value not in list"); return NULL; } diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 900db864621a84..8b8afa3880082f 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2982,7 +2982,7 @@ memoryview_index_impl(PyMemoryViewObject *self, PyObject *value, } } - PyErr_SetString(PyExc_ValueError, "memoryview.index(x): x not found"); + PyErr_SetString(PyExc_ValueError, "value not in memoryview"); return NULL; } diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 55b7f108730728..89f191be80d024 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -680,7 +680,7 @@ range_index(PyObject *self, PyObject *ob) } /* object is not in the range */ - PyErr_SetString(PyExc_ValueError, "range.index(x): x not in range"); + PyErr_SetString(PyExc_ValueError, "value not in range"); return NULL; } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 753c270f525976..255950acba7da6 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -681,7 +681,7 @@ tuple_index_impl(PyTupleObject *self, PyObject *value, Py_ssize_t start, else if (cmp < 0) return NULL; } - PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple"); + PyErr_SetString(PyExc_ValueError, "value not in tuple"); return NULL; }