]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-154788: Make curses window.getparent() unconditional (GH-154789)
authorVyron Vasileiadis <hi@fedonman.com>
Wed, 29 Jul 2026 06:07:15 +0000 (09:07 +0300)
committerGitHub <noreply@github.com>
Wed, 29 Jul 2026 06:07:15 +0000 (09:07 +0300)
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.

Lib/test/test_curses.py
Modules/_cursesmodule.c

index 9f7f8535b6d9a80b1bbc5d5092c02e7d1fcaa8bc..4e5d5f1da0be95ed5636e7781a486f48ad4a24b2 100644 (file)
@@ -278,6 +278,14 @@ class TestCurses(unittest.TestCase):
         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 @@ class TestCurses(unittest.TestCase):
         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)
 
index 01ea3c43cce2e6fac4f4deffc21ff61124dae72c..a913a7a0babe3561bf09d8ed4ef661ea697a21c5 100644 (file)
@@ -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."},