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/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index f65baa0cfae2ad..02b5b2b6c18657 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -371,7 +371,7 @@ def test_simpleops(self): element.remove(subelement) self.serialize_check(element, '') # 5 with self.assertRaisesRegex(ValueError, - r'Element\.remove\(.+\): element not found'): + r" not in "): element.remove(subelement) self.serialize_check(element, '') # 6 element[0:0] = [subelement, subelement, subelement] diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py index dafe5b1b8a0c3f..f4306a3cafb11a 100644 --- a/Lib/xml/etree/ElementTree.py +++ b/Lib/xml/etree/ElementTree.py @@ -271,7 +271,7 @@ def remove(self, subelement): self._children.remove(subelement) except ValueError: # to align the error message with the C implementation - raise ValueError("Element.remove(x): element not found") from None + raise ValueError(f"{subelement!r} not in {self!r}") from None def find(self, path, namespaces=None): """Find first matching element by tag name or path. 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 3ba48d5d9d3c64..dba7e8a3765a45 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1302,7 +1302,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; } @@ -1472,7 +1472,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/_elementtree.c b/Modules/_elementtree.c index 9263f14b57f972..6923f2bcc05763 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1679,8 +1679,7 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement) } if (rc == 0) { - PyErr_SetString(PyExc_ValueError, - "Element.remove(x): element not found"); + PyErr_Format(PyExc_ValueError, "%R not in %R", subelement, self); return NULL; } diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index d97cf7af767ca3..f0789b71eabae3 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1233,7 +1233,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; } @@ -1285,7 +1285,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 8adad8407d04d4..297193dcc44cb5 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2206,8 +2206,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 c519485c1cc74c..6f4b655da2f77a 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1293,7 +1293,7 @@ bytearray_index_impl(PyByteArrayObject *self, PyObject *sub, /*[clinic end generated code: output=067a1e78efc672a7 input=c37f177cfee19fe4]*/ { return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), - sub, start, end); + sub, start, end, "bytearray"); } /*[clinic input] @@ -1331,7 +1331,7 @@ bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub, /*[clinic end generated code: output=38e1cf66bafb08b9 input=7d198b3d6b0a62ce]*/ { return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), - sub, start, end); + sub, start, end, "bytearray"); } static int @@ -2207,7 +2207,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 de8ab26db1e966..816210c3665c9e 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1965,7 +1965,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] @@ -2001,7 +2001,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 5905a6d335b311..bbf8341b91dd80 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3306,7 +3306,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; } @@ -3376,7 +3376,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 f1232f389210ea..26b3540ac3410a 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2894,7 +2894,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 f8cdfe68a6435e..0a6d21d52ce8cc 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -665,7 +665,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 1fa4bae638a1fe..a80a392a079b31 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -585,7 +585,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; }