diff --git a/Lib/operator.py b/Lib/operator.py index 1b765522f85949..be3c1b079e2afd 100644 --- a/Lib/operator.py +++ b/Lib/operator.py @@ -153,7 +153,7 @@ def xor(a, b): def concat(a, b): "Same as a + b, for a and b sequences." - if not hasattr(a, '__getitem__'): + if not hasattr(type(a), '__getitem__'): msg = "'%s' object can't be concatenated" % type(a).__name__ raise TypeError(msg) return a + b @@ -356,7 +356,7 @@ def iand(a, b): def iconcat(a, b): "Same as a += b, for a and b sequences." - if not hasattr(a, '__getitem__'): + if not hasattr(type(a), '__getitem__'): msg = "'%s' object can't be concatenated" % type(a).__name__ raise TypeError(msg) a += b diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py index 1f89986c777ced..c60329b96202a9 100644 --- a/Lib/test/test_operator.py +++ b/Lib/test/test_operator.py @@ -160,6 +160,12 @@ def test_concat(self): self.assertEqual(operator.concat(Seq1([5, 6]), Seq1([7])), [5, 6, 7]) self.assertEqual(operator.concat(Seq2([5, 6]), Seq2([7])), [5, 6, 7]) self.assertRaises(TypeError, operator.concat, 13, 29) + class A: + pass + a = A() + a.__getitem__ = lambda: "spam" + self.assertRaisesRegex(TypeError, "object can't be concatenated", + operator.concat, a, a) def test_countOf(self): operator = self.module @@ -551,6 +557,13 @@ def test_iconcat_without_getitem(self): with self.assertRaisesRegex(TypeError, msg): operator.iconcat(1, 0.5) + class A: + pass + a = A() + a.__getitem__ = lambda: "spam" + self.assertRaisesRegex(TypeError, "object can't be concatenated", + operator.iconcat, a, a) + def test_index(self): operator = self.module class X: diff --git a/Misc/NEWS.d/next/Library/2026-04-03-04-17-59.gh-issue-62912.T6jQf5.rst b/Misc/NEWS.d/next/Library/2026-04-03-04-17-59.gh-issue-62912.T6jQf5.rst new file mode 100644 index 00000000000000..01320d991b5d3d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-03-04-17-59.gh-issue-62912.T6jQf5.rst @@ -0,0 +1,3 @@ +Fix :func:`operator.concat` and :func:`operator.iconcat` to return a correct +exception message, if the object class lacks the :meth:`~object.__getitem__` +dunder. Patch by Sergey B Kirpichev.