https://github.com/python/cpython/commit/6af6165c21ddc6adc6208d69606dbdcdbdb06418
commit: 6af6165c21ddc6adc6208d69606dbdcdbdb06418
branch: main
author: Vyron Vasileiadis <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-07-29T09:07:15+03:00
summary:
gh-154788: Make curses window.getparent() unconditional (GH-154789)
getparent() calls no curses function, it returns the window's stored parent,
but it was compiled only when the ncurses extension functions were present.
Close the guard after getscrreg(), which does need it.
The test moves out of test_state_getters, which is gated on is_scrollok(), so
that getparent() is covered on backends without the extensions.
files:
M Lib/test/test_curses.py
M Modules/_cursesmodule.c
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index 9f7f8535b6d9a8..4e5d5f1da0be95 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -278,6 +278,14 @@ def test_subwindows_references(self):
del win2
gc_collect()
+ def test_getparent(self):
+ # getparent() calls no curses function, so it works with any backend
+ # and is not gated like the is_*() getters below.
+ stdscr = self.stdscr
+ self.assertIsNone(stdscr.getparent())
+ sub = stdscr.subwin(3, 3, 0, 0)
+ self.assertIs(sub.getparent(), stdscr)
+
def test_dupwin(self):
win = curses.newwin(5, 10, 2, 3)
win.addstr(0, 0, 'ABCDE')
@@ -1771,13 +1779,11 @@ def test_state_getters(self):
stdscr.setscrreg(5, 10)
self.assertEqual(stdscr.getscrreg(), (5, 10))
- # is_pad()/is_subwin()/getparent().
+ # is_pad()/is_subwin().
self.assertIs(stdscr.is_pad(), False)
self.assertIs(stdscr.is_subwin(), False)
- self.assertIsNone(stdscr.getparent())
sub = stdscr.subwin(3, 3, 0, 0)
self.assertIs(sub.is_subwin(), True)
- self.assertIs(sub.getparent(), stdscr)
pad = curses.newpad(5, 5)
self.assertIs(pad.is_pad(), True)
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 01ea3c43cce2e6..a913a7a0babe35 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -1936,6 +1936,7 @@ PyCursesWindow_getscrreg(PyObject *op, PyObject
*Py_UNUSED(ignored))
}
return Py_BuildValue("(ii)", top, bottom);
}
+#endif /* NCURSES_EXT_FUNCS >= 20110404 || PDCURSES */
static PyObject *
PyCursesWindow_getparent(PyObject *op, PyObject *Py_UNUSED(ignored))
@@ -1948,7 +1949,6 @@ PyCursesWindow_getparent(PyObject *op, PyObject
*Py_UNUSED(ignored))
}
return Py_NewRef((PyObject *)self->orig);
}
-#endif /* NCURSES_EXT_FUNCS >= 20110404 || PDCURSES */
Window_NoArgNoReturnVoidFunction(wsyncup)
Window_NoArgNoReturnVoidFunction(wsyncdown)
@@ -5061,11 +5061,9 @@ static PyMethodDef PyCursesWindow_methods[] = {
{"getmaxyx", PyCursesWindow_getmaxyx, METH_NOARGS,
"getmaxyx($self, /)\n--\n\n"
"Return a tuple (y, x) of the window height and width."},
-#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20110404) ||
defined(PDCURSES)
{"getparent", PyCursesWindow_getparent, METH_NOARGS,
"getparent($self, /)\n--\n\n"
"Return the parent window, or None if this is not a subwindow."},
-#endif
{"getparyx", PyCursesWindow_getparyx, METH_NOARGS,
"getparyx($self, /)\n--\n\n"
"Return (y, x) relative to the parent window, or (-1, -1) if none."},
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]