https://github.com/python/cpython/commit/286b51257a60cbb29ccf3e1cd80db54497b88a10
commit: 286b51257a60cbb29ccf3e1cd80db54497b88a10
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-06-28T12:35:37+03:00
summary:

gh-152470: Make wide-character curses functions work on a narrow build 
(GH-152476)

curses.window.get_wch, curses.window.get_wstr, curses.unget_wch,
curses.erasewchar, curses.killwchar and curses.wunctrl now also work when
Python is built against a non-wide curses library, on an 8-bit locale, where
each character is a single byte in the relevant encoding.  curses.ungetch now
also accepts a one-character string, like curses.unget_wch.

Co-authored-by: Claude Opus 4.8 <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-06-28-12-00-00.gh-issue-152470.Wn7Kp3.rst
M Doc/library/curses.rst
M Doc/whatsnew/3.16.rst
M Lib/test/test_curses.py
M Misc/NEWS.d/next/Library/2026-06-20-02-14-55.gh-issue-151757.TP9A2x.rst
M Modules/_cursesmodule.c
M Modules/clinic/_cursesmodule.c.h

diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
index d2f11949c04c3f..8987e82ee5d026 100644
--- a/Doc/library/curses.rst
+++ b/Doc/library/curses.rst
@@ -206,17 +206,15 @@ The module :mod:`!curses` defines the following functions:
 
 .. function:: erasechar()
 
-   Return the user's current erase character as a one-byte bytes object.  
Under Unix operating systems this
-   is a property of the controlling tty of the curses program, and is not set 
by
-   the curses library itself.
+   Return the user's current erase character as a raw byte, a :class:`bytes`
+   object of length 1.  See also :func:`erasewchar`.
 
 
 .. function:: erasewchar()
 
-   Return the user's current erase character as a one-character string.
-   This is the wide-character variant of :func:`erasechar`.  Availability
-   depends on building Python against a wide-character-aware version of the
-   underlying curses library.
+   Return the user's current erase character as a one-character :class:`str`.
+   Under Unix operating systems this is a property of the controlling tty of 
the
+   curses program, and is not set by the curses library itself.
 
    .. versionadded:: next
 
@@ -493,17 +491,15 @@ The module :mod:`!curses` defines the following functions:
 
 .. function:: killchar()
 
-   Return the user's current line kill character as a one-byte bytes object. 
Under Unix operating systems
-   this is a property of the controlling tty of the curses program, and is not 
set
-   by the curses library itself.
+   Return the user's current line kill character as a raw byte, a 
:class:`bytes`
+   object of length 1.  See also :func:`killwchar`.
 
 
 .. function:: killwchar()
 
-   Return the user's current line kill character as a one-character string.
-   This is the wide-character variant of :func:`killchar`.  Availability
-   depends on building Python against a wide-character-aware version of the
-   underlying curses library.
+   Return the user's current line kill character as a one-character 
:class:`str`.
+   Under Unix operating systems this is a property of the controlling tty of 
the
+   curses program, and is not set by the curses library itself.
 
    .. versionadded:: next
 
@@ -910,30 +906,39 @@ The module :mod:`!curses` defines the following functions:
 .. function:: unctrl(ch)
 
    Return a bytes object which is a printable representation of the character 
*ch*.
-   Control characters are represented as a caret followed by the character, for
-   example as ``b'^C'``. Printing characters are left as they are.
+   *ch* cannot be a character that does not fit in a single byte; use
+   :func:`wunctrl` for those.
 
 
 .. function:: wunctrl(ch)
 
-   Return a string which is a printable representation of the wide character 
*ch*.
-   Control characters are represented as a caret followed by the character, for
-   example as ``'^C'``.  Printing characters are left as they are.  This is the
-   wide-character variant of :func:`unctrl`, returning a :class:`str` rather 
than
-   :class:`bytes`.  Availability depends on building Python against a
-   wide-character-aware version of the underlying curses library.
+   Return a string which is a printable representation of the character *ch*;
+   any attributes and color pair are ignored.
+   ASCII control characters are represented as a caret followed by a character,
+   for example as ``'^C'``.  Printing characters, including non-ASCII 
characters
+   printable in the locale, are left as they are.  The representation of other
+   characters is defined by the underlying curses library.
 
    .. versionadded:: next
 
 
 .. function:: ungetch(ch)
 
-   Push *ch* so the next :meth:`~window.getch` will return it.
+   Push *ch* so the next :meth:`~window.getch` or :meth:`~window.get_wch` will
+   return it.
+
+   *ch* may be an integer (a key code or character code), a byte, or a string 
of
+   length 1.  A one-character string is pushed like :func:`unget_wch`; on a
+   narrow build it must encode to a single byte.
 
    .. note::
 
       Only one *ch* can be pushed before :meth:`!getch` is called.
 
+   .. versionchanged:: next
+      A one-character string argument is no longer required to encode to a 
single
+      byte, except on a narrow build.
+
 
 .. function:: update_lines_cols()
 
@@ -953,6 +958,10 @@ The module :mod:`!curses` defines the following functions:
 
    .. versionadded:: 3.3
 
+   .. versionchanged:: next
+      Also available on a narrow build, where *ch* must encode to a single byte
+      (an 8-bit locale).
+
 
 .. function:: ungetmouse(id, x, y, z, bstate)
 
@@ -1323,15 +1332,16 @@ Window objects
 .. method:: window.getbkgd()
 
    Return the given window's current background character/attribute pair.
+   It cannot represent a background set with a wide character or with a color
+   pair outside the :func:`color_pair` range; use :meth:`getbkgrnd` for those.
 
 
 .. method:: window.getbkgrnd()
 
    Return the given window's current background as a :class:`complexchar`.
-   This is the wide-character variant of :meth:`getbkgd`: the returned object
-   carries the background character together with its attributes and color 
pair,
-   and the color pair is not limited to the value that fits in a
-   :func:`color_pair`.
+   Unlike :meth:`getbkgd`, the returned object carries the background character
+   together with its attributes and color pair, and the color pair is not 
limited
+   to the value that fits in a :func:`color_pair`.
 
    .. versionadded:: next
 
@@ -1342,16 +1352,23 @@ Window objects
    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.
+   A multibyte character is returned as its encoded bytes one at a time; use
+   :meth:`get_wch` to read it as a single character.
 
 
 .. 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.
+   function keys, keypad keys, and other special keys.  Unlike :meth:`getch`, 
an
+   ordinary key is returned as a one-character :class:`str`.
    In no-delay mode, raise an exception if there is no input.
 
    .. versionadded:: 3.3
 
+   .. versionchanged:: next
+      Also available on a narrow build, where only a character representable 
as a
+      single byte (an 8-bit locale) can be returned.
+
 
 .. method:: window.getdelay()
 
@@ -1407,6 +1424,8 @@ Window objects
    Read a bytes object from the user, with primitive line editing capacity.
    At most *n* characters are read;
    *n* defaults to and cannot exceed 2047.
+   A multibyte character is returned as its encoded bytes; use :meth:`get_wstr`
+   to read the input as a :class:`str`.
 
    .. versionchanged:: 3.14
       The maximum value for *n* was increased from 1023 to 2047.
@@ -1418,9 +1437,8 @@ Window objects
             window.get_wstr(y, x, n)
 
    Read a string from the user, with primitive line editing capacity.
-   This is the wide-character variant of :meth:`getstr`: it returns a
-   :class:`str` rather than a :class:`bytes` object, so it can return
-   characters that are not representable in the window's encoding.
+   Unlike :meth:`getstr`, it can return characters that are not representable 
in
+   the window's encoding.
    At most *n* characters are read; *n* defaults to and cannot exceed 2047.
 
    .. versionadded:: next
@@ -1470,15 +1488,17 @@ Window objects
 
    Return the character at the given position in the window. The bottom 8 bits 
are
    the character proper, and upper bits are the attributes.
+   It cannot represent a cell holding combining characters, a character that 
does
+   not fit in a single byte, or a color pair outside the :func:`color_pair`
+   range; use :meth:`in_wch` for those.
 
 
 .. method:: window.in_wch([y, x])
 
    Return the complex character at the given position in the window as a
-   :class:`complexchar`.  This is the wide-character variant of :meth:`inch`:
-   the returned object carries the cell's text (a spacing character optionally
-   followed by combining characters) together with its attributes and color
-   pair, none of which :meth:`inch` can represent.
+   :class:`complexchar`.  Unlike :meth:`inch`, the returned object carries the
+   cell's text (a spacing character optionally followed by combining 
characters)
+   together with its attributes and color pair.
 
    .. versionadded:: next
 
@@ -1548,6 +1568,8 @@ Window objects
    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.
+   A character not representable in the window's encoding cannot be returned;
+   use :meth:`in_wstr` for those.
 
    .. versionchanged:: 3.14
       The maximum value for *n* was increased from 1023 to 2047.
@@ -1557,11 +1579,10 @@ Window objects
             window.in_wstr(y, x[, n])
 
    Return a string of characters, extracted from the window starting at the
-   current cursor position, or at *y*, *x* if specified.  This is the
-   wide-character variant of :meth:`instr`: it returns a :class:`str` rather
-   than a :class:`bytes` object, so it can return characters that are not
-   representable in the window's encoding.  Attributes and color information
-   are stripped from the characters.  The maximum value for *n* is 2047.
+   current cursor position, or at *y*, *x* if specified.  Unlike :meth:`instr`,
+   it can return characters that are not representable in the window's 
encoding.
+   Attributes and color information are stripped from the characters.  The
+   maximum value for *n* is 2047.
 
    .. versionadded:: next
 
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index a87d708e3fcdc2..cbe0df1c8a65ff 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -113,12 +113,20 @@ curses
   :func:`curses.erasechar`, :func:`curses.killchar` and :func:`curses.unctrl`.
   On a narrow (non-ncursesw) build the character cell holds a single character
   without combining marks, representable as one byte in the window's encoding,
-  and :meth:`~curses.window.in_wstr` returns its decoded text;
-  :meth:`~curses.window.get_wstr` and the :func:`curses.erasewchar`,
-  :func:`curses.killwchar` and :func:`curses.wunctrl` functions require the
-  wide-character ncursesw library.
+  and :meth:`~curses.window.in_wstr` returns its decoded text.
   (Contributed by Serhiy Storchaka in :gh:`151757`.)
 
+* The wide-character :mod:`curses` functions and methods
+  :meth:`~curses.window.get_wch`, :meth:`~curses.window.get_wstr`,
+  :func:`curses.unget_wch`, :func:`curses.erasewchar`,
+  :func:`curses.killwchar` and :func:`curses.wunctrl` now also work when Python
+  is not built against a wide-character-aware curses library, on an 8-bit
+  locale, where each character is a single byte in the relevant encoding.
+  :func:`curses.ungetch` now also accepts a one-character string, like
+  :func:`curses.unget_wch`; on a wide-character build it can be any character
+  (previously a multibyte character raised :exc:`OverflowError`).
+  (Contributed by Serhiy Storchaka in :gh:`152470`.)
+
 * Add :func:`curses.nofilter`, which undoes the effect of 
:func:`curses.filter`.
   (Contributed by Serhiy Storchaka in :gh:`151744`.)
 
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index 7611771aa83e0c..079e69a52c1504 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -42,6 +42,31 @@ def wrapped(self, *args, **kwargs):
         return wrapped
     return deco
 
+def _wide_build():
+    # True on a build that stores wide-character cells (built against 
ncursesw).
+    # A wide build accepts a spacing character plus a combining mark in a 
single
+    # cell; a narrow build accepts only one character per cell.  This stays a
+    # reliable wide/narrow signal even as the wide-character functions 
(get_wch()
+    # and friends) become available on narrow builds too, because the
+    # multi-codepoint cell capacity itself is build-specific.
+    if not hasattr(curses, 'complexchar'):
+        return hasattr(curses.window, 'get_wch')
+    try:
+        curses.complexchar('e\u0301')  # 'e' + combining acute: two code points
+    except ValueError:
+        return False
+    return True
+
+WIDE_BUILD = _wide_build()
+
+def requires_wide_build(test):
+    @functools.wraps(test)
+    def wrapped(self, *args, **kwargs):
+        if not WIDE_BUILD:
+            raise unittest.SkipTest('requires a wide-character curses build')
+        test(self, *args, **kwargs)
+    return wrapped
+
 
 def requires_colors(test):
     @functools.wraps(test)
@@ -332,7 +357,7 @@ def _storable(self, s):
         # one byte.
         if not self._encodable(s):
             return False
-        if hasattr(self.stdscr, 'get_wch'):  # wide build
+        if WIDE_BUILD:
             return True
         return len(s.encode(self.stdscr.encoding)) == len(s)
 
@@ -347,7 +372,7 @@ def _read_char(self, y, x):
             return str(stdscr.in_wch(y, x))
         return stdscr.instr(y, x, 1).decode(stdscr.encoding)
 
-    @requires_curses_window_meth('get_wch')
+    @requires_wide_build
     def test_addch_combining(self):
         stdscr = self.stdscr
         stdscr.move(0, 0)
@@ -368,7 +393,7 @@ def test_addch_combining(self):
         self.assertRaises(ValueError, stdscr.addch, '\n\u0301')
         self.assertRaises(ValueError, stdscr.addch, '\ne\u0301')
 
-    @requires_curses_window_meth('get_wch')
+    @requires_wide_build
     def test_addch_emoji(self):
         # curses has no grapheme-cluster support: a cell holds one spacing
         # character plus zero-width combining characters.  A lone emoji fits,
@@ -385,7 +410,7 @@ def test_addch_emoji(self):
         self.assertRaises(ValueError, stdscr.addch,
                           '\U0001f468\u200d\U0001f469')    # man ZWJ woman
 
-    @requires_curses_window_meth('get_wch')
+    @requires_wide_build
     def test_wide_characters(self):
         # Wide and combining characters in the character-cell methods.
         stdscr = self.stdscr
@@ -407,7 +432,6 @@ def test_wide_characters(self):
         # border() and box() cannot mix integer and wide-string characters.
         self.assertRaises(TypeError, stdscr.box, vline, ord('-'))
 
-    @requires_curses_func('complexchar')
     def test_complexchar_in_cell_methods(self):
         # Every single-character-cell method also accepts a complexchar, whose
         # attributes and color pair come from the cell itself.
@@ -438,7 +462,6 @@ def test_complexchar_in_cell_methods(self):
         self.assertRaises(TypeError, stdscr.hline, h, 3, curses.A_BOLD)
         self.assertRaises(TypeError, stdscr.vline, v, 3, curses.A_BOLD)
 
-    @requires_curses_window_meth('in_wstr')
     def test_in_wstr(self):
         # The wide-character window read returns a str (instr returns bytes).
         # See _encodable for the character set.
@@ -455,7 +478,6 @@ def test_in_wstr(self):
                     self.assertEqual(stdscr.in_wstr(0, 0, len(s)), s)
                     self.assertIsInstance(stdscr.instr(0, 0, len(s)), bytes)
 
-    @requires_curses_func('complexchar')
     def test_complexchar(self):
         # A complexchar is a styled wide-character cell: str() is its text,
         # and the attr and pair attributes are its rendition.
@@ -499,7 +521,6 @@ def test_complexchar(self):
         self.assertRaises(ValueError, curses.complexchar, 'A', 0, -1)
         self.assertRaises(ValueError, curses.complexchar, 'ab')
 
-    @requires_curses_window_meth('in_wch')
     def test_in_wch(self):
         # in_wch() returns the styled wide cell as a complexchar -- something
         # inch() (a packed chtype) cannot represent.
@@ -518,7 +539,6 @@ def test_in_wch(self):
         stdscr.move(0, 0)
         self.assertEqual(str(stdscr.in_wch()), 'A')
 
-    @requires_curses_window_meth('in_wch')
     @requires_colors
     def test_in_wch_color(self):
         # Unlike the chtype methods (which pack the pair into the value via
@@ -532,7 +552,6 @@ def test_in_wch_color(self):
         self.assertEqual(cc.pair, 1)
         self.assertEqual(curses.complexchar('A', 0, 1).pair, 1)
 
-    @requires_curses_window_meth('getbkgrnd')
     def test_getbkgrnd(self):
         # getbkgrnd() returns the background as a complexchar (getbkgd() can
         # only return a packed chtype).
@@ -550,7 +569,6 @@ def test_getbkgrnd(self):
                     self.assertEqual(str(stdscr.getbkgrnd()), ch)
         stdscr.bkgd(' ')
 
-    @requires_curses_func('complexstr')
     def test_complexstr(self):
         # A complexstr is an immutable run of styled wide-character cells: the
         # string counterpart of complexchar (as str is to a single character).
@@ -602,7 +620,7 @@ def test_complexstr(self):
         base = 'é'  # 'e' + combining acute: two code points, one cell
         # Combining sequences need wide-character cells (a narrow build stores
         # one byte per cell).
-        if hasattr(curses.window, 'get_wch') and self._encodable(base):
+        if WIDE_BUILD and self._encodable(base):
             self.assertEqual(len(curses.complexstr(base)), 1)
             self.assertEqual(curses.complexstr(base)[0], cc(base))
             self.assertEqual(len(curses.complexstr('a' + base + 'b')), 3)
@@ -635,7 +653,6 @@ def test_complexstr(self):
         self.assertRaises(TypeError,
                           lambda: curses.complexstr(['A'], pair=0))
 
-    @requires_curses_window_meth('in_wchstr')
     def test_in_wchstr(self):
         # in_wchstr() returns a complexstr -- the styled-cell counterpart of
         # instr() (bytes) and in_wstr() (str), which both strip the rendition.
@@ -655,7 +672,6 @@ def test_in_wchstr(self):
         stdscr.move(0, 0)
         self.assertEqual(str(stdscr.in_wchstr())[:3], 'AbC')
 
-    @requires_curses_window_meth('in_wchstr')
     def test_complexstr_in_write_methods(self):
         # addstr/addnstr/insstr/insnstr also accept a complexstr, written via
         # the wide-character functions; a plain str keeps its current meaning.
@@ -750,11 +766,8 @@ def test_output_character(self):
         # str is stored as a wide-character cell on a wide build, so every
         # encodable character round-trips, insch() included.  A multibyte
         # character does not fit a cell on a narrow build and is skipped.
-        wide = hasattr(stdscr, 'get_wch')
         for c in ('é', '¤', '€', 'є'):
-            if not self._encodable(c):
-                continue
-            if not wide and len(c.encode(encoding)) != 1:
+            if not self._storable(c):
                 continue
             with self.subTest(c=c):
                 stdscr.addch(0, 0, c)
@@ -998,7 +1011,6 @@ def test_getstr(self):
         self.assertEqual(win.getstr(), b'amet')
         self.assertEqual(win.instr(1, 0), b'amet dolor  ')
 
-    @requires_curses_window_meth('get_wstr')
     def test_get_wstr(self):
         # get_wstr() reads input as a str (getstr() returns bytes); feed it 
with
         # unget_wch().  See _encodable for the character set.
@@ -1010,7 +1022,7 @@ def test_get_wstr(self):
                   'naïve ¤',     # ISO-8859-1
                   'soupçon €',   # ISO-8859-15
                   'дяк']:   # KOI8-U
-            if self._encodable(s):
+            if self._storable(s):
                 with self.subTest(s=s):
                     win.erase()
                     for ch in reversed(s + '\n'):
@@ -1465,7 +1477,6 @@ def test_unctrl(self):
         self.assertRaises(TypeError, curses.unctrl, '')
         self.assertRaises(TypeError, curses.unctrl, 'AB')
 
-    @requires_curses_func('wunctrl')
     def test_wunctrl(self):
         # The wide-character variant of unctrl() returns a str.
         self.assertEqual(curses.wunctrl(b'A'), 'A')
@@ -1475,12 +1486,14 @@ def test_wunctrl(self):
         self.assertEqual(curses.wunctrl(10), '^J')
         # See _encodable for the character set (all printable here).
         for c in ('A', 'é', '¤', '€', 'є'):
-            self.assertEqual(curses.wunctrl(c), c)
+            if self._storable(c):
+                self.assertEqual(curses.wunctrl(c), c)
         self.assertRaises(TypeError, curses.wunctrl, b'')
         self.assertRaises(TypeError, curses.wunctrl, b'AB')
         self.assertRaises(TypeError, curses.wunctrl, '')
-        # More than one spacing character is not a single cell.
-        self.assertRaises(ValueError, curses.wunctrl, 'AB')
+        if WIDE_BUILD:
+            # More than one spacing character is not a single cell.
+            self.assertRaises(ValueError, curses.wunctrl, 'AB')
         self.assertRaises(OverflowError, curses.unctrl, 2**64)
 
     def test_endwin(self):
@@ -1552,14 +1565,12 @@ def test_env_queries(self):
             tty_fd = None
         if tty_fd is not None:
             os.close(tty_fd)
-            if hasattr(curses, 'erasewchar'):
-                c = curses.erasewchar()
-                self.assertIsInstance(c, str)
-                self.assertEqual(len(c), 1)
-            if hasattr(curses, 'killwchar'):
-                c = curses.killwchar()
-                self.assertIsInstance(c, str)
-                self.assertEqual(len(c), 1)
+            c = curses.erasewchar()
+            self.assertIsInstance(c, str)
+            self.assertEqual(len(c), 1)
+            c = curses.killwchar()
+            self.assertIsInstance(c, str)
+            self.assertEqual(len(c), 1)
 
     @requires_curses_func('define_key')
     def test_key_management(self):
@@ -2434,30 +2445,40 @@ def test_issue6243(self):
         curses.ungetch(1025)
         self.stdscr.getkey()
 
-    @requires_curses_func('unget_wch')
+    @unittest.skipIf(getattr(curses, 'ncurses_version', (99,)) < (5, 8),
+                     "unget_wch is broken in ncurses 5.7 and earlier")
+    def test_ungetch_wch(self):
+        # ungetch() also accepts a character, like unget_wch(), and it
+        # round-trips through get_wch() -- including a character that does not
+        # fit in a single byte.
+        stdscr = self.stdscr
+        for ch in ('a', '\xe9', '\xa4', '€', 'є', '\U0010FFFF'):
+            if not self._storable(ch):
+                continue
+            curses.ungetch(ch)
+            self.assertEqual(stdscr.get_wch(), ch)
+        # An int is a raw keycode, not a character codepoint.
+        curses.ungetch(curses.KEY_LEFT)
+        self.assertEqual(stdscr.getch(), curses.KEY_LEFT)
+
     @unittest.skipIf(getattr(curses, 'ncurses_version', (99,)) < (5, 8),
                      "unget_wch is broken in ncurses 5.7 and earlier")
     def test_unget_wch(self):
         stdscr = self.stdscr
         encoding = stdscr.encoding
-        # See _encodable for the character set, plus a non-BMP character.
+        # See _storable for the character set, plus a non-BMP character.
         for ch in ('a', '\xe9', '\xa4', '\u20ac', '\u0454', '\U0010FFFF'):
-            try:
-                ch.encode(encoding)
-            except UnicodeEncodeError:
+            if not self._storable(ch):
                 continue
             try:
                 curses.unget_wch(ch)
             except Exception as err:
                 self.fail("unget_wch(%a) failed with encoding %s: %s"
-                          % (ch, stdscr.encoding, err))
-            read = stdscr.get_wch()
-            self.assertEqual(read, ch)
-
-            code = ord(ch)
-            curses.unget_wch(code)
-            read = stdscr.get_wch()
-            self.assertEqual(read, ch)
+                          % (ch, encoding, err))
+            self.assertEqual(stdscr.get_wch(), ch)
+
+            curses.unget_wch(ord(ch))
+            self.assertEqual(stdscr.get_wch(), ch)
 
     def test_encoding(self):
         stdscr = self.stdscr
diff --git 
a/Misc/NEWS.d/next/Library/2026-06-20-02-14-55.gh-issue-151757.TP9A2x.rst 
b/Misc/NEWS.d/next/Library/2026-06-20-02-14-55.gh-issue-151757.TP9A2x.rst
index 421c58298823c0..ee1aa3eff6f0c2 100644
--- a/Misc/NEWS.d/next/Library/2026-06-20-02-14-55.gh-issue-151757.TP9A2x.rst
+++ b/Misc/NEWS.d/next/Library/2026-06-20-02-14-55.gh-issue-151757.TP9A2x.rst
@@ -6,6 +6,4 @@ the functions :func:`curses.erasewchar`, 
:func:`curses.killwchar` and
 :func:`curses.wunctrl`.  On a narrow (non-ncursesw) build the character cell
 holds a single character without combining marks, representable as one byte in
 the window's encoding, and :meth:`curses.window.in_wstr` returns its decoded
-text; :meth:`curses.window.get_wstr` and the :func:`curses.erasewchar`,
-:func:`curses.killwchar` and :func:`curses.wunctrl` functions require the
-wide-character ncursesw library.
+text.
diff --git 
a/Misc/NEWS.d/next/Library/2026-06-28-12-00-00.gh-issue-152470.Wn7Kp3.rst 
b/Misc/NEWS.d/next/Library/2026-06-28-12-00-00.gh-issue-152470.Wn7Kp3.rst
new file mode 100644
index 00000000000000..445e0a1b18f7dd
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-28-12-00-00.gh-issue-152470.Wn7Kp3.rst
@@ -0,0 +1,9 @@
+The wide-character :mod:`curses` functions and methods
+:meth:`curses.window.get_wch`, :meth:`curses.window.get_wstr`,
+:func:`curses.unget_wch`, :func:`curses.erasewchar`, :func:`curses.killwchar`
+and :func:`curses.wunctrl` now also work when Python is not built against a
+wide-character-aware curses library, on an 8-bit locale, where each character
+is a single byte in the relevant encoding.  :func:`curses.ungetch` now also
+accepts a one-character string, like :func:`curses.unget_wch`; on a
+wide-character build it can be any character (previously a multibyte character
+raised :exc:`OverflowError`).
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 7b9de46cf22ab4..5a0d175b5e997e 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -3238,7 +3238,6 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, 
int group_right_1,
     }
 }
 
-#ifdef HAVE_NCURSESW
 /*[clinic input]
 _curses.window.get_wch
 
@@ -3261,6 +3260,7 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, 
int group_right_1,
                             int y, int x)
 /*[clinic end generated code: output=9f4f86e91fe50ef3 input=dd7e5367fb49dc48]*/
 {
+#ifdef HAVE_NCURSESW
     int ct;
     wint_t rtn;
 
@@ -3282,8 +3282,31 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, 
int group_right_1,
         return PyLong_FromLong(rtn);
     else
         return PyUnicode_FromOrdinal(rtn);
-}
+#else
+    /* Without the wide library, read one key with wgetch(): a value above 255
+       is a function key (returned as an int); a byte is decoded with the
+       window's encoding (8-bit locales). */
+    int rtn;
+    Py_BEGIN_ALLOW_THREADS
+    if (!group_right_1) {
+        rtn = wgetch(self->win);
+    }
+    else {
+        rtn = mvwgetch(self->win, y, x);
+    }
+    Py_END_ALLOW_THREADS
+
+    if (rtn == ERR) {
+        const char *funcname = group_right_1 ? "mvwgetch" : "wgetch";
+        return curses_check_signals_on_input_error(self, funcname, "get_wch");
+    }
+    if (rtn > 255) {
+        return PyLong_FromLong(rtn);
+    }
+    char ch = (char)rtn;
+    return PyUnicode_Decode(&ch, 1, self->encoding, NULL);
 #endif
+}
 
 /*
  * Helper function for parsing parameters from getstr() and instr().
@@ -3336,16 +3359,17 @@ PyDoc_STRVAR(_curses_window_getstr__doc__,
 "  n\n"
 "    Maximal number of characters.");
 
+/* Read user input into a new bytes object (empty on ERR), with primitive line
+   editing.  Shared by getstr() and, without the wide library, by get_wstr(). 
*/
 static PyObject *
-PyCursesWindow_getstr(PyObject *op, PyObject *args)
+curses_window_getstr_bytes(PyCursesWindowObject *self, PyObject *args,
+                           const char *funcname)
 {
-    PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
     int rtn, use_xy = 0, y = 0, x = 0;
     unsigned int max_buf_size = 2048;
     unsigned int n = max_buf_size - 1;
 
-    if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy,
-                                           "_curses.window.instr"))
+    if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, 
funcname))
     {
         return NULL;
     }
@@ -3381,6 +3405,13 @@ PyCursesWindow_getstr(PyObject *op, PyObject *args)
     return PyBytesWriter_FinishWithSize(writer, strlen(buf));
 }
 
+static PyObject *
+PyCursesWindow_getstr(PyObject *op, PyObject *args)
+{
+    PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+    return curses_window_getstr_bytes(self, args, "_curses.window.getstr");
+}
+
 /*[clinic input]
 _curses.window.hline
 
@@ -3566,16 +3597,18 @@ PyDoc_STRVAR(_curses_window_instr__doc__,
 "instr() returns a string at most n characters long (exclusive of\n"
 "the trailing NUL).");
 
+/* Extract characters from the window into a new bytes object (empty on ERR),
+   with attributes and color stripped.  Shared by instr() and, without the wide
+   library, by in_wstr(). */
 static PyObject *
-PyCursesWindow_instr(PyObject *op, PyObject *args)
+curses_window_instr_bytes(PyCursesWindowObject *self, PyObject *args,
+                          const char *funcname)
 {
-    PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
     int rtn, use_xy = 0, y = 0, x = 0;
     unsigned int max_buf_size = 2048;
     unsigned int n = max_buf_size - 1;
 
-    if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy,
-                                           "_curses.window.instr"))
+    if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, 
funcname))
     {
         return NULL;
     }
@@ -3601,7 +3634,13 @@ PyCursesWindow_instr(PyObject *op, PyObject *args)
     return PyBytesWriter_FinishWithSize(writer, strlen(buf));
 }
 
-#ifdef HAVE_NCURSESW
+static PyObject *
+PyCursesWindow_instr(PyObject *op, PyObject *args)
+{
+    PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+    return curses_window_instr_bytes(self, args, "_curses.window.instr");
+}
+
 PyDoc_STRVAR(_curses_window_get_wstr__doc__,
 "get_wstr([[y, x,] n=2047])\n"
 "Read a string from the user, with primitive line editing capacity.\n"
@@ -3619,6 +3658,7 @@ static PyObject *
 PyCursesWindow_get_wstr(PyObject *op, PyObject *args)
 {
     PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+#ifdef HAVE_NCURSESW
     int rtn, use_xy = 0, y = 0, x = 0;
     unsigned int max_buf_size = 2048;
     unsigned int n = max_buf_size - 1;
@@ -3668,8 +3708,21 @@ PyCursesWindow_get_wstr(PyObject *op, PyObject *args)
     PyMem_Free(wbuf);
     PyMem_Free(buf);
     return res;
-}
+#else
+    /* Without the wide library, read the bytes as getstr() does and decode 
them
+       with the window's encoding. */
+    PyObject *bytes = curses_window_getstr_bytes(self, args,
+                                                 "_curses.window.get_wstr");
+    if (bytes == NULL) {
+        return NULL;
+    }
+    PyObject *res = PyUnicode_Decode(PyBytes_AS_STRING(bytes),
+                                     PyBytes_GET_SIZE(bytes),
+                                     self->encoding, NULL);
+    Py_DECREF(bytes);
+    return res;
 #endif /* HAVE_NCURSESW */
+}
 
 PyDoc_STRVAR(_curses_window_in_wstr__doc__,
 "in_wstr([y, x,] n=2047)\n"
@@ -3688,6 +3741,7 @@ static PyObject *
 PyCursesWindow_in_wstr(PyObject *op, PyObject *args)
 {
     PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+#ifdef HAVE_NCURSESW
     int rtn, use_xy = 0, y = 0, x = 0;
     unsigned int max_buf_size = 2048;
     unsigned int n = max_buf_size - 1;
@@ -3699,7 +3753,6 @@ PyCursesWindow_in_wstr(PyObject *op, PyObject *args)
     }
 
     n = Py_MIN(n, max_buf_size - 1);
-#ifdef HAVE_NCURSESW
     wchar_t *buf = PyMem_New(wchar_t, n + 1);
     if (buf == NULL) {
         return PyErr_NoMemory();
@@ -3720,26 +3773,17 @@ PyCursesWindow_in_wstr(PyObject *op, PyObject *args)
     PyMem_Free(buf);
     return res;
 #else
-    /* Without the wide library, read the locale-encoded bytes and decode them
+    /* Without the wide library, read the bytes as instr() does and decode them
        with the window's encoding. */
-    char *buf = PyMem_New(char, n + 1);
-    if (buf == NULL) {
-        return PyErr_NoMemory();
-    }
-
-    if (use_xy) {
-        rtn = mvwinnstr(self->win, y, x, buf, n);
-    }
-    else {
-        rtn = winnstr(self->win, buf, n);
-    }
-
-    if (rtn == ERR) {
-        PyMem_Free(buf);
-        return Py_GetConstant(Py_CONSTANT_EMPTY_STR);
+    PyObject *bytes = curses_window_instr_bytes(self, args,
+                                                "_curses.window.in_wstr");
+    if (bytes == NULL) {
+        return NULL;
     }
-    PyObject *res = PyUnicode_Decode(buf, strlen(buf), self->encoding, NULL);
-    PyMem_Free(buf);
+    PyObject *res = PyUnicode_Decode(PyBytes_AS_STRING(bytes),
+                                     PyBytes_GET_SIZE(bytes),
+                                     self->encoding, NULL);
+    Py_DECREF(bytes);
     return res;
 #endif
 }
@@ -4835,12 +4879,10 @@ static PyMethodDef PyCursesWindow_methods[] = {
         "getstr", PyCursesWindow_getstr, METH_VARARGS,
         _curses_window_getstr__doc__
     },
-#ifdef HAVE_NCURSESW
     {
         "get_wstr", PyCursesWindow_get_wstr, METH_VARARGS,
         _curses_window_get_wstr__doc__
     },
-#endif
     {"getyx", PyCursesWindow_getyx, METH_NOARGS,
      "getyx($self, /)\n--\n\n"
      "Return a tuple (y, x) of the current cursor position."},
@@ -5686,7 +5728,6 @@ _curses_erasechar_impl(PyObject *module)
     return PyBytes_FromStringAndSize(&ch, 1);
 }
 
-#ifdef HAVE_NCURSESW
 /*[clinic input]
 _curses.erasewchar
 
@@ -5697,17 +5738,24 @@ static PyObject *
 _curses_erasewchar_impl(PyObject *module)
 /*[clinic end generated code: output=7f3bd8c9097ac456 input=f7e9a3893b4df2f8]*/
 {
-    wchar_t ch;
-
     PyCursesStatefulInitialised(module);
 
+#ifdef HAVE_NCURSESW
+    wchar_t ch;
+
     if (erasewchar(&ch) == ERR) {
         curses_set_error(module, "erasewchar", NULL);
         return NULL;
     }
     return PyUnicode_FromWideChar(&ch, 1);
+#else
+    /* Without the wide library, decode the single-byte erase character
+       with the screen's encoding. */
+    char ch = erasechar();
+
+    return PyUnicode_Decode(&ch, 1, curses_screen_encoding, NULL);
+#endif
 }
-#endif /* HAVE_NCURSESW */
 
 /*[clinic input]
 _curses.flash
@@ -6890,7 +6938,6 @@ _curses_killchar_impl(PyObject *module)
     return PyBytes_FromStringAndSize(&ch, 1);
 }
 
-#ifdef HAVE_NCURSESW
 /*[clinic input]
 _curses.killwchar
 
@@ -6901,6 +6948,7 @@ static PyObject *
 _curses_killwchar_impl(PyObject *module)
 /*[clinic end generated code: output=eac1fd72a0c88d42 input=5c2d7d1ab2f24eb7]*/
 {
+#ifdef HAVE_NCURSESW
     wchar_t ch;
 
     if (killwchar(&ch) == ERR) {
@@ -6908,8 +6956,14 @@ _curses_killwchar_impl(PyObject *module)
         return NULL;
     }
     return PyUnicode_FromWideChar(&ch, 1);
+#else
+    /* Without the wide library, decode the single-byte kill character
+       with the screen's encoding. */
+    char ch = killchar();
+
+    return PyUnicode_Decode(&ch, 1, curses_screen_encoding, NULL);
+#endif
 }
-#endif /* HAVE_NCURSESW */
 
 /*[clinic input]
 _curses.longname
@@ -7783,7 +7837,6 @@ _curses_unctrl(PyObject *module, PyObject *ch)
     return PyBytes_FromString(res);
 }
 
-#ifdef HAVE_NCURSESW
 /*[clinic input]
 _curses.wunctrl
 
@@ -7800,12 +7853,13 @@ static PyObject *
 _curses_wunctrl(PyObject *module, PyObject *ch)
 /*[clinic end generated code: output=7b16d5534ff05728 input=9ceb6749118bd07c]*/
 {
+    PyCursesStatefulInitialised(module);
+
+#ifdef HAVE_NCURSESW
     chtype ch_;
     wchar_t wstr[CCHARW_MAX + 1];
     cchar_t wcval;
 
-    PyCursesStatefulInitialised(module);
-
     int type = PyCurses_ConvertToCchar_t(NULL, ch, &ch_, wstr);
     if (type == 0) {
         return NULL;
@@ -7826,33 +7880,24 @@ _curses_wunctrl(PyObject *module, PyObject *ch)
         return NULL;
     }
     return PyUnicode_FromWideChar(res, -1);
-}
-#endif /* HAVE_NCURSESW */
-
-/*[clinic input]
-_curses.ungetch
-
-    ch: object
-    /
-
-Push ch so the next getch() will return it.
-[clinic start generated code]*/
-
-static PyObject *
-_curses_ungetch(PyObject *module, PyObject *ch)
-/*[clinic end generated code: output=9b19d8268376d887 input=6681e6ae4c42e5eb]*/
-{
+#else
+    /* Without the wide library, fall back to the single-byte unctrl() and
+       decode its result with the screen's encoding. */
     chtype ch_;
 
-    PyCursesStatefulInitialised(module);
-
-    if (!PyCurses_ConvertToChtype(NULL, ch, &ch_))
+    if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) {
         return NULL;
+    }
 
-    return curses_check_err(module, ungetch(ch_), "ungetch", NULL);
+    const char *res = unctrl(ch_);
+    if (res == NULL) {
+        curses_set_null_error(module, "unctrl", "wunctrl");
+        return NULL;
+    }
+    return PyUnicode_Decode(res, strlen(res), curses_screen_encoding, NULL);
+#endif
 }
 
-#ifdef HAVE_NCURSESW
 /* Convert an object to a character (wchar_t):
 
     - int
@@ -7900,6 +7945,40 @@ PyCurses_ConvertToWchar_t(PyObject *obj,
     }
 }
 
+/*[clinic input]
+_curses.ungetch
+
+    ch: object
+    /
+
+Push ch so the next getch() will return it.
+[clinic start generated code]*/
+
+static PyObject *
+_curses_ungetch(PyObject *module, PyObject *ch)
+/*[clinic end generated code: output=9b19d8268376d887 input=6681e6ae4c42e5eb]*/
+{
+    PyCursesStatefulInitialised(module);
+
+#ifdef HAVE_NCURSESW
+    /* Push a str through the wide queue, so a character that does not fit in a
+       single byte round-trips to get_wch().  An int stays a raw value (a 
keycode
+       or a byte) for getch(); use unget_wch() to push it as a character. */
+    if (PyUnicode_Check(ch)) {
+        wchar_t wch;
+        if (!PyCurses_ConvertToWchar_t(ch, &wch))
+            return NULL;
+        return curses_check_err(module, unget_wch(wch), "unget_wch", 
"ungetch");
+    }
+#endif
+
+    chtype ch_;
+    if (!PyCurses_ConvertToChtype(NULL, ch, &ch_))
+        return NULL;
+
+    return curses_check_err(module, ungetch(ch_), "ungetch", NULL);
+}
+
 /*[clinic input]
 _curses.unget_wch
 
@@ -7919,9 +7998,33 @@ _curses_unget_wch(PyObject *module, PyObject *ch)
 
     if (!PyCurses_ConvertToWchar_t(ch, &wch))
         return NULL;
+#ifdef HAVE_NCURSESW
     return curses_check_err(module, unget_wch(wch), "unget_wch", NULL);
-}
+#else
+    /* Without the wide library there is no unget_wch(): encode the character 
as
+       a single screen-encoding byte and push that.  Narrow builds support only
+       8-bit locales, so a character that does not fit in one byte is 
rejected. */
+    PyObject *str = PyUnicode_FromWideChar(&wch, 1);
+    if (str == NULL) {
+        return NULL;
+    }
+    PyObject *bytes = PyUnicode_AsEncodedString(str, curses_screen_encoding,
+                                                NULL);
+    Py_DECREF(str);
+    if (bytes == NULL) {
+        return NULL;
+    }
+    if (PyBytes_GET_SIZE(bytes) != 1) {
+        Py_DECREF(bytes);
+        PyErr_SetString(PyExc_OverflowError,
+                        "character does not fit in a single byte");
+        return NULL;
+    }
+    int b = (unsigned char)PyBytes_AS_STRING(bytes)[0];
+    Py_DECREF(bytes);
+    return curses_check_err(module, ungetch(b), "ungetch", "unget_wch");
 #endif
+}
 
 #ifdef HAVE_CURSES_USE_ENV
 /*[clinic input]
diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h
index f895090bef845f..8e0f922ad0444f 100644
--- a/Modules/clinic/_cursesmodule.c.h
+++ b/Modules/clinic/_cursesmodule.c.h
@@ -1271,8 +1271,6 @@ _curses_window_getkey(PyObject *self, PyObject *args)
     return return_value;
 }
 
-#if defined(HAVE_NCURSESW)
-
 PyDoc_STRVAR(_curses_window_get_wch__doc__,
 "get_wch([y, x])\n"
 "Get a wide character from terminal keyboard.\n"
@@ -1319,8 +1317,6 @@ _curses_window_get_wch(PyObject *self, PyObject *args)
     return return_value;
 }
 
-#endif /* defined(HAVE_NCURSESW) */
-
 PyDoc_STRVAR(_curses_window_hline__doc__,
 "hline([y, x,] ch, n, [attr])\n"
 "Display a horizontal line.\n"
@@ -2784,8 +2780,6 @@ _curses_erasechar(PyObject *module, PyObject 
*Py_UNUSED(ignored))
     return _curses_erasechar_impl(module);
 }
 
-#if defined(HAVE_NCURSESW)
-
 PyDoc_STRVAR(_curses_erasewchar__doc__,
 "erasewchar($module, /)\n"
 "--\n"
@@ -2804,8 +2798,6 @@ _curses_erasewchar(PyObject *module, PyObject 
*Py_UNUSED(ignored))
     return _curses_erasewchar_impl(module);
 }
 
-#endif /* defined(HAVE_NCURSESW) */
-
 PyDoc_STRVAR(_curses_flash__doc__,
 "flash($module, /)\n"
 "--\n"
@@ -4097,8 +4089,6 @@ _curses_killchar(PyObject *module, PyObject 
*Py_UNUSED(ignored))
     return _curses_killchar_impl(module);
 }
 
-#if defined(HAVE_NCURSESW)
-
 PyDoc_STRVAR(_curses_killwchar__doc__,
 "killwchar($module, /)\n"
 "--\n"
@@ -4117,8 +4107,6 @@ _curses_killwchar(PyObject *module, PyObject 
*Py_UNUSED(ignored))
     return _curses_killwchar_impl(module);
 }
 
-#endif /* defined(HAVE_NCURSESW) */
-
 PyDoc_STRVAR(_curses_longname__doc__,
 "longname($module, /)\n"
 "--\n"
@@ -5316,8 +5304,6 @@ PyDoc_STRVAR(_curses_unctrl__doc__,
 #define _CURSES_UNCTRL_METHODDEF    \
     {"unctrl", (PyCFunction)_curses_unctrl, METH_O, _curses_unctrl__doc__},
 
-#if defined(HAVE_NCURSESW)
-
 PyDoc_STRVAR(_curses_wunctrl__doc__,
 "wunctrl($module, ch, /)\n"
 "--\n"
@@ -5330,8 +5316,6 @@ PyDoc_STRVAR(_curses_wunctrl__doc__,
 #define _CURSES_WUNCTRL_METHODDEF    \
     {"wunctrl", (PyCFunction)_curses_wunctrl, METH_O, _curses_wunctrl__doc__},
 
-#endif /* defined(HAVE_NCURSESW) */
-
 PyDoc_STRVAR(_curses_ungetch__doc__,
 "ungetch($module, ch, /)\n"
 "--\n"
@@ -5341,8 +5325,6 @@ PyDoc_STRVAR(_curses_ungetch__doc__,
 #define _CURSES_UNGETCH_METHODDEF    \
     {"ungetch", (PyCFunction)_curses_ungetch, METH_O, _curses_ungetch__doc__},
 
-#if defined(HAVE_NCURSESW)
-
 PyDoc_STRVAR(_curses_unget_wch__doc__,
 "unget_wch($module, ch, /)\n"
 "--\n"
@@ -5352,8 +5334,6 @@ PyDoc_STRVAR(_curses_unget_wch__doc__,
 #define _CURSES_UNGET_WCH_METHODDEF    \
     {"unget_wch", (PyCFunction)_curses_unget_wch, METH_O, 
_curses_unget_wch__doc__},
 
-#endif /* defined(HAVE_NCURSESW) */
-
 #if defined(HAVE_CURSES_USE_ENV)
 
 PyDoc_STRVAR(_curses_use_env__doc__,
@@ -5487,10 +5467,6 @@ _curses_has_extended_color_support(PyObject *module, 
PyObject *Py_UNUSED(ignored
     #define _CURSES_WINDOW_ENCLOSE_METHODDEF
 #endif /* !defined(_CURSES_WINDOW_ENCLOSE_METHODDEF) */
 
-#ifndef _CURSES_WINDOW_GET_WCH_METHODDEF
-    #define _CURSES_WINDOW_GET_WCH_METHODDEF
-#endif /* !defined(_CURSES_WINDOW_GET_WCH_METHODDEF) */
-
 #ifndef _CURSES_WINDOW_NOUTREFRESH_METHODDEF
     #define _CURSES_WINDOW_NOUTREFRESH_METHODDEF
 #endif /* !defined(_CURSES_WINDOW_NOUTREFRESH_METHODDEF) */
@@ -5519,10 +5495,6 @@ _curses_has_extended_color_support(PyObject *module, 
PyObject *Py_UNUSED(ignored
     #define _CURSES_IS_RAW_METHODDEF
 #endif /* !defined(_CURSES_IS_RAW_METHODDEF) */
 
-#ifndef _CURSES_ERASEWCHAR_METHODDEF
-    #define _CURSES_ERASEWCHAR_METHODDEF
-#endif /* !defined(_CURSES_ERASEWCHAR_METHODDEF) */
-
 #ifndef _CURSES_GETSYX_METHODDEF
     #define _CURSES_GETSYX_METHODDEF
 #endif /* !defined(_CURSES_GETSYX_METHODDEF) */
@@ -5591,10 +5563,6 @@ _curses_has_extended_color_support(PyObject *module, 
PyObject *Py_UNUSED(ignored
     #define _CURSES_IS_TERM_RESIZED_METHODDEF
 #endif /* !defined(_CURSES_IS_TERM_RESIZED_METHODDEF) */
 
-#ifndef _CURSES_KILLWCHAR_METHODDEF
-    #define _CURSES_KILLWCHAR_METHODDEF
-#endif /* !defined(_CURSES_KILLWCHAR_METHODDEF) */
-
 #ifndef _CURSES_MOUSEINTERVAL_METHODDEF
     #define _CURSES_MOUSEINTERVAL_METHODDEF
 #endif /* !defined(_CURSES_MOUSEINTERVAL_METHODDEF) */
@@ -5623,14 +5591,6 @@ _curses_has_extended_color_support(PyObject *module, 
PyObject *Py_UNUSED(ignored
     #define _CURSES_TYPEAHEAD_METHODDEF
 #endif /* !defined(_CURSES_TYPEAHEAD_METHODDEF) */
 
-#ifndef _CURSES_WUNCTRL_METHODDEF
-    #define _CURSES_WUNCTRL_METHODDEF
-#endif /* !defined(_CURSES_WUNCTRL_METHODDEF) */
-
-#ifndef _CURSES_UNGET_WCH_METHODDEF
-    #define _CURSES_UNGET_WCH_METHODDEF
-#endif /* !defined(_CURSES_UNGET_WCH_METHODDEF) */
-
 #ifndef _CURSES_USE_ENV_METHODDEF
     #define _CURSES_USE_ENV_METHODDEF
 #endif /* !defined(_CURSES_USE_ENV_METHODDEF) */
@@ -5642,4 +5602,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=bbf6d77a5813b1e1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=f48f8e3554b30b86 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]

Reply via email to