Skip to content

Complete the missing core curses bindings #160141

Open

Description

@cdorsman

Feature or enhancement

CPython's _curses module does not expose the complete core curses API.
Several bindings are missing or incomplete compared with the underlying
ncurses interface.

The missing functionality includes terminal and termcap operations,
video operations, soft-label operations, mcprint(), and
ripoffline(). Some related curses functionality is already present in
the current development branch but needs to be completed and integrated
consistently with the current stateful module architecture.

This issue intentionally concerns the core curses API only. The curses
form and menu APIs are separate and are not part of this issue.

Proposed solution

Port the remaining core curses bindings using the current CPython
module-state and Argument Clinic conventions, and add the corresponding
tests and documentation.

Has this already been discussed elsewhere?

No response given

Links to previous discussion of this feature:

No response

Linked PRs

Activity

  1. gvanrossum commented on Oct 21, 2026

    @gvanrossum
    Member

    @serhiy-storchaka Is this is your wheelhouse?

  2. picnixz commented on Oct 21, 2026

    @picnixz
    Member

    Unless Serhiy supports this addition, please do not open a PR.

  3. added a commit that references this issue on Oct 21, 2026
  4. serhiy-storchaka commented on Oct 22, 2026

    @serhiy-storchaka
    Member

    Thank you for your interest in curses, but the module is not stagnant. It was significantly extended in 3.16 and now covers almost the full curses API: multiple screens (newterm(), set_term()), Unicode text and combining characters (complexchar and complexstr), extended colors and color pairs, WA_* attributes, soft-label keys, more mouse and key-management functions, and many of the smaller missing functions. See the curses section of "What's New in Python 3.16".

    The remaining functions are missing not by accident:

    • tgetent(), tgetflag(), tgetnum(), tgetstr() and tgoto() are the obsolete termcap interface. Their terminfo equivalents tigetflag(), tigetnum(), tigetstr() and tparm() are already available. Also, tgetent() calls setupterm() internally and replaces the current terminal.
    • vidattr(), vidputs() and tputs() write directly to the terminal, bypassing the curses screen, so curses loses track of the actual attributes. Programs that work at the terminfo level can use tparm() and putp().
    • mcprint() sends data to a printer attached to the terminal, which is hardly useful today.
    • ripoffline() needs a careful design: the C callback has no user data and is called inside initscr() or newterm(), where exceptions cannot be propagated, and the window it receives is owned by curses and must not be deleted by Python. There is also an ncurses bug that makes it unsafe with multiple screens (https://lists.gnu.org/archive/html/bug-ncurses/2026-10/msg00009.html). The implementation in gh-160141: Curses core fixes #160142 deletes that window as soon as the callback returns, which leads to a use-after-free.

    The menu and form libraries are tracked in #44985. I have four alternative prototypes for both of them (a direct C binding, a pure Python implementation, and two more Pythonic APIs), but they are large, and their memory ownership rules do not map well to Python, so the choice between them needs a design discussion first.

    If you have a concrete use case for any of these functions, please describe it here, and we can discuss what API would fit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirpendingThe issue will be closed if no feedback is providedtopic-cursestype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions