Skip to content

Commit a52f428

Browse files
gh-151776: Add curses state-query functions (GH-151778)
Add window methods and module functions that report curses state which could previously only be set: the window getters is_cleared(), is_idcok(), is_idlok(), is_immedok(), is_keypad(), is_leaveok(), is_nodelay(), is_notimeout(), is_pad(), is_scrollok(), is_subwin(), is_syncok(), getdelay(), getparent() and getscrreg(), and the functions is_cbreak(), is_echo(), is_nl() and is_raw(). They are available when built against an ncurses with NCURSES_EXT_FUNCS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e0909f0 commit a52f428

7 files changed

Lines changed: 502 additions & 1 deletion

File tree

Doc/library/curses.rst

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,41 @@ The module :mod:`!curses` defines the following functions:
398398
no flushing is done.
399399

400400

401+
.. function:: is_cbreak()
402+
403+
Return ``True`` if cbreak mode (see :func:`cbreak`) is enabled,
404+
``False`` otherwise.
405+
Availability: ncurses 6.5 or later.
406+
407+
.. versionadded:: next
408+
409+
410+
.. function:: is_echo()
411+
412+
Return ``True`` if echo mode (see :func:`echo`) is enabled,
413+
``False`` otherwise.
414+
Availability: ncurses 6.5 or later.
415+
416+
.. versionadded:: next
417+
418+
419+
.. function:: is_nl()
420+
421+
Return ``True`` if nl mode (see :func:`nl`) is enabled, ``False`` otherwise.
422+
Availability: ncurses 6.5 or later.
423+
424+
.. versionadded:: next
425+
426+
427+
.. function:: is_raw()
428+
429+
Return ``True`` if raw mode (see :func:`raw`) is enabled,
430+
``False`` otherwise.
431+
Availability: ncurses 6.5 or later.
432+
433+
.. versionadded:: next
434+
435+
401436
.. function:: is_term_resized(nlines, ncols)
402437

403438
Return ``True`` if :func:`resize_term` would modify the window structure,
@@ -1154,6 +1189,16 @@ Window objects
11541189
.. versionadded:: 3.3
11551190

11561191

1192+
.. method:: window.getdelay()
1193+
1194+
Return the window's read timeout in milliseconds,
1195+
as set by :meth:`nodelay` or :meth:`timeout`:
1196+
``-1`` for blocking, ``0`` for non-blocking,
1197+
or a positive number of milliseconds.
1198+
1199+
.. versionadded:: next
1200+
1201+
11571202
.. method:: window.getkey([y, x])
11581203

11591204
Get a character, returning a string instead of an integer, as :meth:`getch`
@@ -1167,13 +1212,29 @@ Window objects
11671212
Return a tuple ``(y, x)`` of the height and width of the window.
11681213

11691214

1215+
.. method:: window.getparent()
1216+
1217+
Return the parent window of this subwindow,
1218+
or ``None`` if this window is not a subwindow.
1219+
1220+
.. versionadded:: next
1221+
1222+
11701223
.. method:: window.getparyx()
11711224

11721225
Return the beginning coordinates of this window relative to its parent window
11731226
as a tuple ``(y, x)``. Return ``(-1, -1)`` if this window has no
11741227
parent.
11751228

11761229

1230+
.. method:: window.getscrreg()
1231+
1232+
Return a tuple ``(top, bottom)`` of the window's current scrolling region,
1233+
as set by :meth:`setscrreg`.
1234+
1235+
.. versionadded:: next
1236+
1237+
11771238
.. method:: window.getstr()
11781239
window.getstr(n)
11791240
window.getstr(y, x)
@@ -1319,13 +1380,98 @@ Window objects
13191380
.. versionadded:: next
13201381

13211382

1383+
.. method:: window.is_cleared()
1384+
1385+
Return the current value set by :meth:`clearok`.
1386+
1387+
.. versionadded:: next
1388+
1389+
1390+
.. method:: window.is_idcok()
1391+
1392+
Return the current value set by :meth:`idcok`.
1393+
1394+
.. versionadded:: next
1395+
1396+
1397+
.. method:: window.is_idlok()
1398+
1399+
Return the current value set by :meth:`idlok`.
1400+
1401+
.. versionadded:: next
1402+
1403+
1404+
.. method:: window.is_immedok()
1405+
1406+
Return the current value set by :meth:`immedok`.
1407+
1408+
.. versionadded:: next
1409+
1410+
1411+
.. method:: window.is_keypad()
1412+
1413+
Return the current value set by :meth:`keypad`.
1414+
1415+
.. versionadded:: next
1416+
1417+
1418+
.. method:: window.is_leaveok()
1419+
1420+
Return the current value set by :meth:`leaveok`.
1421+
1422+
.. versionadded:: next
1423+
1424+
13221425
.. method:: window.is_linetouched(line)
13231426

13241427
Return ``True`` if the specified line was modified since the last call to
13251428
:meth:`refresh`; otherwise return ``False``. Raise a :exc:`curses.error`
13261429
exception if *line* is not valid for the given window.
13271430

13281431

1432+
.. method:: window.is_nodelay()
1433+
1434+
Return the current value set by :meth:`nodelay`.
1435+
1436+
.. versionadded:: next
1437+
1438+
1439+
.. method:: window.is_notimeout()
1440+
1441+
Return the current value set by :meth:`notimeout`.
1442+
1443+
.. versionadded:: next
1444+
1445+
1446+
.. method:: window.is_pad()
1447+
1448+
Return ``True`` if the window is a pad created by :func:`newpad`.
1449+
1450+
.. versionadded:: next
1451+
1452+
1453+
.. method:: window.is_scrollok()
1454+
1455+
Return the current value set by :meth:`scrollok`.
1456+
1457+
.. versionadded:: next
1458+
1459+
1460+
.. method:: window.is_subwin()
1461+
1462+
Return ``True`` if the window is a subwindow created by :meth:`subwin`
1463+
or :meth:`derwin`.
1464+
1465+
.. versionadded:: next
1466+
1467+
1468+
.. method:: window.is_syncok()
1469+
1470+
Return the current value set by :meth:`syncok`.
1471+
1472+
.. versionadded:: next
1473+
1474+
13291475
.. method:: window.is_wintouched()
13301476

13311477
Return ``True`` if the specified window was modified since the last call to

Doc/whatsnew/3.16.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ curses
125125
support.
126126
(Contributed by Serhiy Storchaka in :gh:`151774`.)
127127

128+
* Add :mod:`curses` functions and window methods that report state which could
129+
previously only be set, such as :meth:`curses.window.is_keypad`,
130+
:meth:`curses.window.getparent` and :func:`curses.is_cbreak`,
131+
available when built against an ncurses with ``NCURSES_EXT_FUNCS``.
132+
(Contributed by Serhiy Storchaka in :gh:`151776`.)
133+
128134
gzip
129135
----
130136

Lib/test/test_curses.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,75 @@ def test_input_options(self):
10281028
stdscr.timeout(0)
10291029
stdscr.timeout(5)
10301030

1031+
@requires_curses_window_meth('is_scrollok')
1032+
def test_state_getters(self):
1033+
stdscr = self.stdscr
1034+
# Each is_*() getter returns the value set by the matching setter.
1035+
for setter, getter in [
1036+
('clearok', 'is_cleared'),
1037+
('idcok', 'is_idcok'),
1038+
('idlok', 'is_idlok'),
1039+
('keypad', 'is_keypad'),
1040+
('leaveok', 'is_leaveok'),
1041+
('nodelay', 'is_nodelay'),
1042+
('notimeout', 'is_notimeout'),
1043+
('scrollok', 'is_scrollok'),
1044+
]:
1045+
getattr(stdscr, setter)(True)
1046+
self.assertIs(getattr(stdscr, getter)(), True)
1047+
getattr(stdscr, setter)(False)
1048+
self.assertIs(getattr(stdscr, getter)(), False)
1049+
if hasattr(stdscr, 'immedok'):
1050+
stdscr.immedok(True)
1051+
self.assertIs(stdscr.is_immedok(), True)
1052+
stdscr.immedok(False)
1053+
if hasattr(stdscr, 'syncok'):
1054+
stdscr.syncok(True)
1055+
self.assertIs(stdscr.is_syncok(), True)
1056+
stdscr.syncok(False)
1057+
1058+
# getdelay() reflects timeout()/nodelay().
1059+
stdscr.timeout(100)
1060+
self.assertEqual(stdscr.getdelay(), 100)
1061+
stdscr.nodelay(True)
1062+
self.assertEqual(stdscr.getdelay(), 0)
1063+
stdscr.timeout(-1)
1064+
self.assertEqual(stdscr.getdelay(), -1)
1065+
1066+
# getscrreg() reflects setscrreg().
1067+
stdscr.setscrreg(5, 10)
1068+
self.assertEqual(stdscr.getscrreg(), (5, 10))
1069+
1070+
# is_pad()/is_subwin()/getparent().
1071+
self.assertIs(stdscr.is_pad(), False)
1072+
self.assertIs(stdscr.is_subwin(), False)
1073+
self.assertIsNone(stdscr.getparent())
1074+
sub = stdscr.subwin(3, 3, 0, 0)
1075+
self.assertIs(sub.is_subwin(), True)
1076+
self.assertIs(sub.getparent(), stdscr)
1077+
pad = curses.newpad(5, 5)
1078+
self.assertIs(pad.is_pad(), True)
1079+
1080+
@requires_curses_func('is_cbreak')
1081+
def test_global_state_getters(self):
1082+
if self.isatty:
1083+
curses.cbreak()
1084+
self.assertIs(curses.is_cbreak(), True)
1085+
curses.nocbreak()
1086+
self.assertIs(curses.is_cbreak(), False)
1087+
curses.raw()
1088+
self.assertIs(curses.is_raw(), True)
1089+
curses.noraw()
1090+
self.assertIs(curses.is_raw(), False)
1091+
curses.echo()
1092+
self.assertIs(curses.is_echo(), True)
1093+
curses.noecho()
1094+
self.assertIs(curses.is_echo(), False)
1095+
curses.nl()
1096+
self.assertIs(curses.is_nl(), True)
1097+
curses.nonl()
1098+
self.assertIs(curses.is_nl(), False)
1099+
10311100
@requires_curses_func('typeahead')
10321101
def test_typeahead(self):
10331102
curses.typeahead(sys.__stdin__.fileno())
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Add :mod:`curses` functions and window methods that report state which could
2+
previously only be set: the window methods :meth:`~curses.window.is_cleared`,
3+
:meth:`~curses.window.is_idcok`, :meth:`~curses.window.is_idlok`,
4+
:meth:`~curses.window.is_immedok`, :meth:`~curses.window.is_keypad`,
5+
:meth:`~curses.window.is_leaveok`, :meth:`~curses.window.is_nodelay`,
6+
:meth:`~curses.window.is_notimeout`, :meth:`~curses.window.is_pad`,
7+
:meth:`~curses.window.is_scrollok`, :meth:`~curses.window.is_subwin`,
8+
:meth:`~curses.window.is_syncok`, :meth:`~curses.window.getdelay`,
9+
:meth:`~curses.window.getparent` and :meth:`~curses.window.getscrreg`, and the
10+
functions :func:`curses.is_cbreak`, :func:`curses.is_echo`,
11+
:func:`curses.is_nl` and :func:`curses.is_raw`. They are only available when
12+
built against an ncurses with ``NCURSES_EXT_FUNCS``.

0 commit comments

Comments
 (0)