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 hasdefine_key/keyok).term_attrs— the X/Open wide attribute query, present only inlibncursesw, so missing from a narrow-lncursesbuild.
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_FUNCprobes forscr_dump(one probe gates the inseparable family),key_defined,term_attrs,define_key,keyok,set_escdelay,set_tabsize.get_escdelay/get_tabsizeread theESCDELAY/TABSIZEvariables, which some libraries declare asextern intrather than macros, so a function probe doesn't fit. Add a smallPY_CHECK_CURSES_VARmacro (tests thatint x = ESCDELAY;compiles) and gate the getters onHAVE_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
- gh-152502: Detect optional curses functions with configure probes #152504
- [3.15] gh-152502: Detect optional curses functions with configure probes (GH-152504) #152589
- [3.13] gh-152502: Detect optional curses functions with configure probes (GH-152504) (GH-152589) #152602
- [3.14] gh-152502: Detect optional curses functions with configure probes (GH-152504) (GH-152589) #152603
- gh-152502: Detect the curses mouse interface and is_* methods portably #152705
- [3.15] gh-152502: Detect the curses mouse interface portably (GH-152705) #152707
- [3.14] gh-152502: Detect the curses mouse interface portably (GH-152705) #152734
- [3.13] gh-152502: Detect the curses mouse interface portably (GH-152705) #152735