Skip to content

curses: detect optional functions with configure probes instead of assuming ncurses #152502

Description

@serhiy-storchaka

Several functions in Modules/_cursesmodule.c are called unconditionally or gated only by the ncurses-specific NCURSES_EXT_FUNCS macro. Both break building or using the module against curses implementations other than ncursesw — narrow (non-wide) ncurses, and third-party curses such as NetBSD curses — even when the library provides the function.

Unconditionally-called functions that aren't universally present (no HAVE_CURSES_* guard, so a library lacking them fails to link):

  • scr_dump/scr_restore/scr_init/scr_set — the whole family is absent from NetBSD curses.
  • key_defined — absent from NetBSD curses (which has define_key/keyok).
  • term_attrs — the X/Open wide attribute query, present only in libncursesw, so missing from a narrow -lncurses build.

Functions gated by NCURSES_EXT_FUNCS that NetBSD implements without defining that macro, so the module silently drops them:

  • define_key, keyok, set_escdelay, set_tabsize, get_escdelay, get_tabsize.

Proposed change: detect each with a configure capability probe and gate on HAVE_CURSES_*.

  • PY_CHECK_CURSES_FUNC probes for scr_dump (one probe gates the inseparable family), key_defined, term_attrs, define_key, keyok, set_escdelay, set_tabsize.
  • get_escdelay/get_tabsize read the ESCDELAY/TABSIZE variables, which some libraries declare as extern int rather than macros, so a function probe doesn't fit. Add a small PY_CHECK_CURSES_VAR macro (tests that int x = ESCDELAY; compiles) and gate the getters on HAVE_CURSES_ESCDELAY/HAVE_CURSES_TABSIZE.

None of these are in X/Open Curses; they are ncurses extensions (NetBSD provides compatible ones), so capability-gating is the correct treatment, and a probe is more portable than conditioning on NCURSES_VERSION.

No behaviour change on standard ncursesw (all macros defined). test_curses passes and is refleak-clean on ncursesw, narrow ncurses, and NetBSD curses, under UTF-8 and 8-bit locales. test_env_queries calls curses.term_attrs() unconditionally and needs a hasattr guard for the narrow case.

Linked PRs

Activity

  1. added
    type-featureA feature request or enhancement
    buildThe build process and cross-build
    on Jun 28, 2026
  2. added 3 commits that reference this issue on Jun 29, 2026
  3. added 2 commits that reference this issue on Jun 29, 2026
  4. serhiy-storchaka commented on Jun 30, 2026

    @serhiy-storchaka
    MemberAuthor

    Reopening: the curses mouse interface (getmouse/ungetmouse/mousemask/mouseinterval/has_mouse/wenclose/wmouse_trafo/mouse_trafo plus the BUTTON* constants) is gated only by the ncurses-specific NCURSES_MOUSE_VERSION macro, so it is dropped on NetBSD curses even though that library provides the whole API. Same treatment as the rest of this issue: gate on configure capability probes (getmouse, has_mouse) and on the presence of the BUTTON* macros instead of NCURSES_MOUSE_VERSION.

  5. added 4 commits that reference this issue on Jun 30, 2026
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

    buildThe build process and cross-buildextension-modulesC modules in the Modules dirtype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions