Skip to content

Commit 326f7f7

Browse files
authored
gh-156963: Raise TypeError when concatenating complexstr with another type (GH-156964)
complexstr_concat() is the sq_concat slot and returned NotImplemented for a non-complexstr operand. PyNumber_Add() returns an sq_concat result verbatim, so the singleton reached Python code instead of a TypeError, and an augmented assignment rebound the name to it.
1 parent 8b2433a commit 326f7f7

2 files changed

Lines changed: 7 additions & 1 deletion

File tree

Lib/test/test_curses.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,9 @@ def test_complexstr(self):
796796
self.assertEqual(str(s[1:]), 'bc')
797797
self.assertEqual(str(s[::-1]), 'cbA')
798798
self.assertEqual(str(s + curses.complexstr(['Z'])), 'AbcZ')
799+
# Concatenating anything else raises instead of returning NotImplemented.
800+
self.assertRaises(TypeError, lambda: s + 'Z')
801+
self.assertRaises(TypeError, lambda: s + cc('Z'))
799802
# The empty complexstr.
800803
self.assertEqual(len(curses.complexstr([])), 0)
801804
self.assertEqual(str(curses.complexstr('')), '')

Modules/_cursesmodule.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1590,7 +1590,10 @@ complexstr_concat(PyObject *a, PyObject *b)
15901590
{
15911591
cursesmodule_state *state = get_cursesmodule_state_by_cls(Py_TYPE(a));
15921592
if (!Py_IS_TYPE(b, state->complexstr_type)) {
1593-
Py_RETURN_NOTIMPLEMENTED;
1593+
PyErr_Format(PyExc_TypeError,
1594+
"can only concatenate complexstr to complexstr, not %T",
1595+
b);
1596+
return NULL;
15941597
}
15951598
PyCursesComplexStrObject *sa = _PyCursesComplexStrObject_CAST(a);
15961599
PyCursesComplexStrObject *sb = _PyCursesComplexStrObject_CAST(b);

0 commit comments

Comments
 (0)