https://github.com/python/cpython/commit/9b7eb47c0766fb9c62ee47d0ad0d16d877154fae
commit: 9b7eb47c0766fb9c62ee47d0ad0d16d877154fae
branch: 3.14
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-23T12:20:30Z
summary:
[3.14] gh-156234: Fix and rewrite the curses documentation on reading
(GH-156235) (GH-156280)
Fix wrong types: instr() and getstr() return a bytes object, not a str, and
their n limits the number of bytes; getkey() returns a str; unctrl() returns
a bytes object. Make clear whether an integer standing for a character is an
encoded byte or a character code.
Rewrite the documentation of getch(), get_wch(), getkey(), getstr() and
instr(), following X/Open Curses.
(cherry picked from commit be87bfa8a1a68516cedc618c7cf5bb7b0b251678)
files:
M Doc/library/curses.rst
M Modules/_cursesmodule.c
M Modules/clinic/_cursesmodule.c.h
diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
index 614e2fa20d03da..cd157403adf9ca 100644
--- a/Doc/library/curses.rst
+++ b/Doc/library/curses.rst
@@ -30,6 +30,8 @@ Linux and the BSD variants of Unix.
Whenever the documentation mentions a *character* it can be specified
as an integer, a one-character Unicode string or a one-byte byte string.
+ An integer is the code of a single encoded byte, optionally combined with
+ attributes and a color pair, as returned by :meth:`window.inch`.
Whenever the documentation mentions a *character string* it can be specified
as a Unicode string or a byte string.
@@ -505,8 +507,8 @@ The module :mod:`!curses` defines the following functions:
.. function:: putp(str)
Equivalent to ``tputs(str, 1, putchar)``; emit the value of a specified
- terminfo capability for the current terminal. Note that the output of
:func:`putp`
- always goes to standard output.
+ terminfo capability, a bytes object, for the current terminal.
+ Note that the output of :func:`putp` always goes to standard output.
:func:`setupterm` (or :func:`initscr`) must be called first.
@@ -677,7 +679,7 @@ The module :mod:`!curses` defines the following functions:
.. function:: tparm(str[, ...])
Instantiate the bytes object *str* with the supplied parameters, where
*str* should
- be a parameterized string obtained from the terminfo database. For example,
+ be a parameterized byte string obtained from the terminfo database. For
example,
``tparm(tigetstr("cup"), 5, 3)`` could result in ``b'\033[6;4H'``, the exact
result depending on terminal type. Up to nine integer parameters may be
supplied.
@@ -698,7 +700,8 @@ The module :mod:`!curses` defines the following functions:
.. function:: unctrl(ch)
- Return a bytes object which is a printable representation of the character
*ch*.
+ Return a bytes object which is a printable representation of the character
*ch*;
+ any attributes and color pair are ignored.
Control characters are represented as a caret followed by the character, for
example as ``b'^C'``. Printing characters are left as they are.
@@ -707,6 +710,9 @@ The module :mod:`!curses` defines the following functions:
Push *ch* so the next :meth:`~window.getch` will return it.
+ *ch* may be an integer (a key code or the code of an encoded byte), a byte,
+ or a string of length 1 which encodes to a single byte.
+
.. note::
Only one *ch* can be pushed before :meth:`!getch` is called.
@@ -724,6 +730,9 @@ The module :mod:`!curses` defines the following functions:
Push *ch* so the next :meth:`~window.get_wch` will return it.
+ *ch* may be an integer (a character code, not a key code) or a string of
+ length 1.
+
.. note::
Only one *ch* can be pushed before :meth:`!get_wch` is called.
@@ -1004,27 +1013,58 @@ Window objects
.. method:: window.getch([y, x])
- Get a character. Note that the integer returned does *not* have to be in
ASCII
- range: function keys, keypad keys and so on are represented by numbers
higher
- than 255. In no-delay mode, return ``-1`` if there is no input, otherwise
- wait until a key is pressed.
+ Read a key press, after moving the cursor to *y*, *x* if specified,
+ and return it as an integer.
+ The window is refreshed first if it is not a pad and was modified since
+ the last refresh.
+ Wait until a key is pressed, or return ``-1`` if the read is non-blocking
+ or times out (see :meth:`nodelay` and :meth:`timeout`).
+
+ An ordinary key is returned as the code of a single byte of its encoding
+ in the current locale,
+ so a character encoded with several bytes takes several calls.
+ For example, in a UTF-8 locale ``'é'`` is read as ``195``, then ``169``.
+ Use :meth:`get_wch` to read it as a single character.
+
+ In keypad mode (see :meth:`keypad`) function keys and other special keys
+ are returned as one of the :ref:`KEY_* constants <curses-key-constants>`,
+ which cannot be mistaken for an ordinary key.
+ Otherwise, or if their escape sequence does not arrive in time
+ (see :meth:`notimeout` and :func:`set_escdelay`),
+ their bytes are returned one at a time.
+
+ In echo mode (see :func:`echo`) the key is added to the window as by
+ :meth:`addch`; special keys are not echoed.
.. method:: window.get_wch([y, x])
- Get a wide character. Return a character for most keys, or an integer for
- function keys, keypad keys, and other special keys.
- In no-delay mode, raise an exception if there is no input.
+ Read a key press, after moving the cursor to *y*, *x* if specified,
+ and return it as a one-character :class:`str`.
+ The window is refreshed first if it is not a pad and was modified since
+ the last refresh.
+ Wait until a key is pressed, or raise :exc:`error` if the read is
+ non-blocking or times out (see :meth:`nodelay` and :meth:`timeout`).
+
+ In keypad mode (see :meth:`keypad`) function keys and other special keys
+ are returned as one of the :ref:`KEY_* constants <curses-key-constants>`,
+ an integer.
+ Otherwise, or if their escape sequence does not arrive in time
+ (see :meth:`notimeout` and :func:`set_escdelay`),
+ their characters are returned one at a time.
+
+ In echo mode (see :func:`echo`) the key is added to the window as by
+ :meth:`addch`; special keys are not echoed.
.. versionadded:: 3.3
.. method:: window.getkey([y, x])
- Get a character, returning a string instead of an integer, as :meth:`getch`
- does. Function keys, keypad keys and other special keys return a multibyte
- string containing the key name. In no-delay mode, raise an exception if
- there is no input.
+ Read a key press as :meth:`getch` does, but return it as a :class:`str`:
+ an ordinary key as a one-character string, the byte decoded as Latin-1,
+ and a special key as its name, such as ``'KEY_UP'`` (see :func:`keyname`).
+ Raise :exc:`error` instead of returning ``-1`` if there is no input.
.. method:: window.getmaxyx()
@@ -1044,8 +1084,11 @@ Window objects
window.getstr(y, x)
window.getstr(y, x, n)
- Read a bytes object from the user, with primitive line editing capacity.
- At most *n* characters are read;
+ Read a line of input from the user, with primitive line editing capacity,
+ after moving the cursor to *y*, *x* if specified.
+ Return it as a bytes object, in the encoding of the current locale
+ and without the terminating newline.
+ At most *n* bytes are read;
*n* defaults to and cannot exceed 2047.
.. versionchanged:: 3.14
@@ -1147,12 +1190,11 @@ Window objects
.. method:: window.instr([n])
window.instr(y, x[, n])
- Return a bytes object of characters, extracted from the window starting at
the
- current cursor position, or at *y*, *x* if specified, and stopping at the
end
- of the line. Attributes and color information are stripped
- from the characters. If *n* is specified, :meth:`instr` returns a string
- at most *n* characters long (exclusive of the trailing NUL).
- The maximum value for *n* is 2047.
+ Read the text of the window from the current cursor position,
+ or from *y*, *x* if specified, to the end of the line,
+ and return it as a bytes object, in the encoding of the current locale.
+ Attributes and color pairs are stripped.
+ At most *n* bytes are read; *n* defaults to and cannot exceed 2047.
.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.
@@ -1176,6 +1218,8 @@ Window objects
If *flag* is ``True``, escape sequences generated by some keys (keypad,
function keys)
will be interpreted by :mod:`!curses`. If *flag* is ``False``, escape
sequences will be
left as is in the input stream.
+ Keypad mode is disabled by default, but :func:`wrapper` enables it for the
+ main window.
.. method:: window.leaveok(flag)
@@ -1528,6 +1572,8 @@ by some methods.
| | color-pair field information |
+-------------------------+-------------------------------+
+.. _curses-key-constants:
+
Keys are referred to by integer constants with names starting with ``KEY_``.
The exact keycaps available are system dependent.
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 48c53fdc68b1f2..6008802b81c68a 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -1547,18 +1547,25 @@ _curses.window.getch
]
/
-Get a character code from terminal keyboard.
+Read a key press and return it as an integer.
-The integer returned does not have to be in ASCII range: function
-keys, keypad keys and so on return numbers higher than 256. In
-no-delay mode, -1 is returned if there is no input, else getch()
-waits until a key is pressed.
+Wait until a key is pressed, or return -1 if the read is
+non-blocking or times out.
+
+An ordinary key is returned as the code of a single byte of its
+encoding in the current locale, so a character encoded with several
+bytes takes several calls. Use get_wch() to read it as a single
+character.
+
+In keypad mode function keys and other special keys are returned as
+one of the KEY_* constants, which cannot be mistaken for an ordinary
+key. Otherwise their bytes are returned one at a time.
[clinic start generated code]*/
static PyObject *
_curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x)
-/*[clinic end generated code: output=e1639e87d545e676 input=0dc5ff40e079787a]*/
+/*[clinic end generated code: output=e1639e87d545e676 input=882ddab9b41afbbd]*/
{
int rtn;
@@ -1595,18 +1602,18 @@ _curses.window.getkey
]
/
-Get a character (string) from terminal keyboard.
+Read a key press and return it as a str.
-Returning a string instead of an integer, as getch() does. Function
-keys, keypad keys and other special keys return a multibyte string
-containing the key name. In no-delay mode, an exception is raised
-if there is no input.
+Read as getch() does, but return an ordinary key as a one-character
+string, the byte decoded as Latin-1, and a special key as its name,
+such as 'KEY_UP'. Raise curses.error instead of returning -1 if
+there is no input.
[clinic start generated code]*/
static PyObject *
_curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x)
-/*[clinic end generated code: output=8490a182db46b10f input=bd24a7da1ed9c73b]*/
+/*[clinic end generated code: output=8490a182db46b10f input=f054cf034c69e879]*/
{
int rtn;
@@ -1655,16 +1662,20 @@ _curses.window.get_wch
]
/
-Get a wide character from terminal keyboard.
+Read a key press and return it as a one-character str.
+
+Wait until a key is pressed, or raise curses.error if the read is
+non-blocking or times out.
-Return a character for most keys, or an integer for function keys,
-keypad keys, and other special keys.
+In keypad mode function keys and other special keys are returned as
+one of the KEY_* constants, an integer. Otherwise their characters
+are returned one at a time.
[clinic start generated code]*/
static PyObject *
_curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x)
-/*[clinic end generated code: output=9f4f86e91fe50ef3 input=dd7e5367fb49dc48]*/
+/*[clinic end generated code: output=9f4f86e91fe50ef3 input=77eb2da426ebe71f]*/
{
int ct;
wint_t rtn;
@@ -1736,14 +1747,14 @@ curses_clinic_parse_optional_xy_n(PyObject *args,
PyDoc_STRVAR(_curses_window_getstr__doc__,
"getstr([[y, x,] n=2047])\n"
-"Read a string from the user, with primitive line editing capacity.\n"
+"Read a line of input and return it as a bytes object.\n"
"\n"
" y\n"
" Y-coordinate.\n"
" x\n"
" X-coordinate.\n"
" n\n"
-" Maximal number of characters.");
+" Maximal number of bytes.");
static PyObject *
PyCursesWindow_getstr(PyObject *op, PyObject *args)
@@ -1974,21 +1985,19 @@ _curses_window_inch_impl(PyCursesWindowObject *self,
int group_right_1,
PyDoc_STRVAR(_curses_window_instr__doc__,
"instr([y, x,] n=2047)\n"
-"Return a string of characters, extracted from the window.\n"
+"Return the text of the window as a bytes object.\n"
"\n"
" y\n"
" Y-coordinate.\n"
" x\n"
" X-coordinate.\n"
" n\n"
-" Maximal number of characters.\n"
+" Maximal number of bytes.\n"
"\n"
-"Return a string of characters, extracted from the window starting\n"
-"at the current cursor position, or at y, x if specified, and\n"
-"stopping at the end of the line. Attributes and color\n"
-"information are stripped from the characters. If n is specified,\n"
-"instr() returns a string at most n characters long (exclusive of\n"
-"the trailing NUL).");
+"Read from the current cursor position, or from y, x if specified, to\n"
+"the end of the line, and return the text in the encoding of the\n"
+"current locale, with attributes and color pairs stripped. At most n\n"
+"bytes are read.");
static PyObject *
PyCursesWindow_instr(PyObject *op, PyObject *args)
@@ -4802,15 +4811,16 @@ _curses.unctrl
ch: object
/
-Return a string which is a printable representation of the character ch.
+Return a bytes object which is a printable representation of ch.
-Control characters are displayed as a caret followed by the character,
-for example as ^C. Printing characters are left as they are.
+Control characters are displayed as a caret followed by the
+character, for example as ^C. Printing characters are left as they
+are. Any attributes and color pair are ignored.
[clinic start generated code]*/
static PyObject *
_curses_unctrl(PyObject *module, PyObject *ch)
-/*[clinic end generated code: output=8e07fafc430c9434 input=cd1e35e16cd1ace4]*/
+/*[clinic end generated code: output=8e07fafc430c9434 input=6732d59733d3ed5b]*/
{
chtype ch_;
diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h
index afcfd407190c93..f647328cb9f590 100644
--- a/Modules/clinic/_cursesmodule.c.h
+++ b/Modules/clinic/_cursesmodule.c.h
@@ -758,17 +758,24 @@ _curses_window_getbkgd(PyObject *self, PyObject
*Py_UNUSED(ignored))
PyDoc_STRVAR(_curses_window_getch__doc__,
"getch([y, x])\n"
-"Get a character code from terminal keyboard.\n"
+"Read a key press and return it as an integer.\n"
"\n"
" y\n"
" Y-coordinate.\n"
" x\n"
" X-coordinate.\n"
"\n"
-"The integer returned does not have to be in ASCII range: function\n"
-"keys, keypad keys and so on return numbers higher than 256. In\n"
-"no-delay mode, -1 is returned if there is no input, else getch()\n"
-"waits until a key is pressed.");
+"Wait until a key is pressed, or return -1 if the read is\n"
+"non-blocking or times out.\n"
+"\n"
+"An ordinary key is returned as the code of a single byte of its\n"
+"encoding in the current locale, so a character encoded with several\n"
+"bytes takes several calls. Use get_wch() to read it as a single\n"
+"character.\n"
+"\n"
+"In keypad mode function keys and other special keys are returned as\n"
+"one of the KEY_* constants, which cannot be mistaken for an ordinary\n"
+"key. Otherwise their bytes are returned one at a time.");
#define _CURSES_WINDOW_GETCH_METHODDEF \
{"getch", (PyCFunction)_curses_window_getch, METH_VARARGS,
_curses_window_getch__doc__},
@@ -806,17 +813,17 @@ _curses_window_getch(PyObject *self, PyObject *args)
PyDoc_STRVAR(_curses_window_getkey__doc__,
"getkey([y, x])\n"
-"Get a character (string) from terminal keyboard.\n"
+"Read a key press and return it as a str.\n"
"\n"
" y\n"
" Y-coordinate.\n"
" x\n"
" X-coordinate.\n"
"\n"
-"Returning a string instead of an integer, as getch() does. Function\n"
-"keys, keypad keys and other special keys return a multibyte string\n"
-"containing the key name. In no-delay mode, an exception is raised\n"
-"if there is no input.");
+"Read as getch() does, but return an ordinary key as a one-character\n"
+"string, the byte decoded as Latin-1, and a special key as its name,\n"
+"such as \'KEY_UP\'. Raise curses.error instead of returning -1 if\n"
+"there is no input.");
#define _CURSES_WINDOW_GETKEY_METHODDEF \
{"getkey", (PyCFunction)_curses_window_getkey, METH_VARARGS,
_curses_window_getkey__doc__},
@@ -856,15 +863,19 @@ _curses_window_getkey(PyObject *self, PyObject *args)
PyDoc_STRVAR(_curses_window_get_wch__doc__,
"get_wch([y, x])\n"
-"Get a wide character from terminal keyboard.\n"
+"Read a key press and return it as a one-character str.\n"
"\n"
" y\n"
" Y-coordinate.\n"
" x\n"
" X-coordinate.\n"
"\n"
-"Return a character for most keys, or an integer for function keys,\n"
-"keypad keys, and other special keys.");
+"Wait until a key is pressed, or raise curses.error if the read is\n"
+"non-blocking or times out.\n"
+"\n"
+"In keypad mode function keys and other special keys are returned as\n"
+"one of the KEY_* constants, an integer. Otherwise their characters\n"
+"are returned one at a time.");
#define _CURSES_WINDOW_GET_WCH_METHODDEF \
{"get_wch", (PyCFunction)_curses_window_get_wch, METH_VARARGS,
_curses_window_get_wch__doc__},
@@ -4217,10 +4228,11 @@ PyDoc_STRVAR(_curses_unctrl__doc__,
"unctrl($module, ch, /)\n"
"--\n"
"\n"
-"Return a string which is a printable representation of the character ch.\n"
+"Return a bytes object which is a printable representation of ch.\n"
"\n"
-"Control characters are displayed as a caret followed by the character,\n"
-"for example as ^C. Printing characters are left as they are.");
+"Control characters are displayed as a caret followed by the\n"
+"character, for example as ^C. Printing characters are left as they\n"
+"are. Any attributes and color pair are ignored.");
#define _CURSES_UNCTRL_METHODDEF \
{"unctrl", (PyCFunction)_curses_unctrl, METH_O, _curses_unctrl__doc__},
@@ -4471,4 +4483,4 @@ _curses_has_extended_color_support(PyObject *module,
PyObject *Py_UNUSED(ignored
#ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */
-/*[clinic end generated code: output=8f8629fba6d86b33 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b267dfb3db6b6f56 input=a9049054013a1b77]*/
_______________________________________________
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]