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

Metadata

Metadata

Assignees

No one assigned

    Labels

    buildThe build process and cross-buildextension-modulesC modules in the Modules dirtype-featureA feature request or enhancement
    No fields configured for issues without a type.

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions