What changed in curses — past month
python/cpython main, window ≈ 2026-06-09 → 2026-07-10 · 51 commits touching the curses module, tests, and docs.
The month was dominated by two large pieces of work — full Unicode / styled-cell support and multiple-terminal support — plus a run of correctness and portability fixes that let the module build and run across ncurses, NetBSD curses, PDCurses and windows-curses. Everything else was comparatively minor.
1. Full Unicode text and styled character cells
The biggest change. The character-cell window methods now accept a full character cell — a spacing character optionally followed by combining characters — anywhere they previously took a single integer or byte character, so the module finally handles wide and combining characters end to end (gh-151757). New wide-character read methods window.get_wstr() / window.in_wstr() and the functions erasewchar(), killwchar(), wunctrl() came with it.
On top of that, two new types make a styled cell a first-class Python object:
curses.complexchar(gh-152233) — one styled character cell: its text, attributes and color pair together.window.in_wch()andwindow.getbkgrnd()return one, and the cell methods (addch,bkgd,border,hline, …) now also accept one. So you can read a decorated cell off the screen and write it back unchanged.curses.complexstr(gh-152233) — an immutable string of styled cells, the counterpart tocomplexchar.window.in_wchstr()returns one;addstr,addnstr,insstrandinsnstrnow accept one, each cell carrying its own attributes and color.
Crucially, all of this works whether or not Python was built against a wide-character-aware (ncursesw) curses library (gh-152470, gh-152233). On a narrow build a cell simply holds a single character with no combining marks, representable as one byte in the window’s encoding — the same API, degraded gracefully rather than absent. curses.textpad.Textbox was lifted onto this foundation and now edits the full Unicode range, not just Latin-1 (gh-133031).
2. Multiple terminals in one process
The second major feature: curses can now drive more than one terminal from a single process (gh-90092), which previously it could not model at all. The change adds:
curses.newterm()— initialize an additional terminal, returning a new screen object (documented as a first-class object with its own lifecycle).curses.set_term()— switch the current terminal.curses.new_prescr()and thewindow.use()method to bind windows to a screen.
Screen state can also be persisted: scr_dump(), scr_restore(), scr_init() and scr_set() dump the whole screen to a file and restore it (gh-152260).
3. Other newly wrapped functions
A batch of smaller X/Open gap-closers, each a straightforward binding: dynamic (extended) color-pair management (gh-151774), state-query functions such as is_cbreak / is_echo / is_raw (gh-151776), window attribute get/set methods with WA_* constants (gh-152219), key management — define_key(), key_defined(), keyok() (gh-152334), soft-label-key (slk_*) functions (gh-152263), term_attrs() (gh-152332), window.dupwin() (gh-152258), nofilter() (gh-151744), and the mouse helpers has_mouse() / window.mouse_trafo() (gh-152325).
4. Fixes, portability and docs
- Correctness: use-after-free of the screen encoding (gh-151695); integer-overflow guards on the chtype / color-pair packing path (gh-152275); the public module name now appears in curses types and exceptions (gh-87904);
Textboxcan edit its last cell (gh-71880). - Build/portability: optional functions detected via configure probes (gh-152502); the mouse interface and
is_*methods detected portably across ncurses / NetBSD / PDCurses / windows-curses (gh-152502); compilation fixed on platforms defining thestdscrmacro (gh-153009) and a macOS build warning silenced (gh-152813); the test suite made portable to other curses implementations (gh-151693). - Docs: the curses documentation was reorganized into topic subsections (gh-152584), the classes documented (gh-87904), missing docstrings added (gh-151623), and results of
inch()/getbkgd()documented (gh-87881).
Availability: the styled-cell types, multiple-terminal support and most new functions are 3.16+; several fixes (portability, overflow guards, Textbox 8-bit-locale support) were backported to 3.13–3.15.