From: Serhiy Storchaka Date: Mon, 29 Jun 2026 15:25:30 +0000 (+0300) Subject: [3.14] gh-152502: Detect optional curses functions with configure probes (GH-152504... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ad8bc2084af81d5db07fa6db61003e3d6fbdb18;p=thirdparty%2FPython%2Fcpython.git [3.14] gh-152502: Detect optional curses functions with configure probes (GH-152504) (GH-152589) (GH-152603) set_escdelay(), set_tabsize() and the ESCDELAY and TABSIZE variables were gated only by the ncurses-specific NCURSES_EXT_FUNCS macro, which excluded them when building against other curses implementations such as NetBSD curses even when they provided them. Detect each with a configure capability probe and gate on HAVE_CURSES_*. (cherry picked from commit 0635e55b47e306aa6cc0610105775849b0699e2c) (cherry picked from commit 2a4ffa6f2128308ba5ba81a7c8912fb781a271e0) Co-authored-by: Claude Opus 4.8 --- diff --git a/Misc/NEWS.d/next/Build/2026-06-28-16-17-55.gh-issue-152502.6SNqMg.rst b/Misc/NEWS.d/next/Build/2026-06-28-16-17-55.gh-issue-152502.6SNqMg.rst new file mode 100644 index 000000000000..cc0fabed10f1 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-06-28-16-17-55.gh-issue-152502.6SNqMg.rst @@ -0,0 +1,5 @@ +The :mod:`curses` module now detects ``set_escdelay()``, ``set_tabsize()`` and +the ``ESCDELAY`` and ``TABSIZE`` variables with :program:`configure` capability +probes instead of the ncurses-specific ``NCURSES_EXT_FUNCS`` macro, so they are +exposed when building against other curses implementations such as NetBSD curses +that provide them. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 1f37f3478b57..52f813406268 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3736,9 +3736,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) Py_RETURN_NONE; } -#if defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102 -// https://invisible-island.net/ncurses/NEWS.html#index-t20080119 - +#ifdef HAVE_CURSES_ESCDELAY /*[clinic input] _curses.get_escdelay @@ -3755,6 +3753,9 @@ _curses_get_escdelay_impl(PyObject *module) { return PyLong_FromLong(ESCDELAY); } +#endif /* HAVE_CURSES_ESCDELAY */ + +#ifdef HAVE_CURSES_SET_ESCDELAY /*[clinic input] _curses.set_escdelay ms: int @@ -3779,7 +3780,9 @@ _curses_set_escdelay_impl(PyObject *module, int ms) return PyCursesCheckERR(module, set_escdelay(ms), "set_escdelay"); } +#endif /* HAVE_CURSES_SET_ESCDELAY */ +#ifdef HAVE_CURSES_TABSIZE /*[clinic input] _curses.get_tabsize @@ -3795,6 +3798,9 @@ _curses_get_tabsize_impl(PyObject *module) { return PyLong_FromLong(TABSIZE); } +#endif /* HAVE_CURSES_TABSIZE */ + +#ifdef HAVE_CURSES_SET_TABSIZE /*[clinic input] _curses.set_tabsize size: int @@ -3818,7 +3824,7 @@ _curses_set_tabsize_impl(PyObject *module, int size) return PyCursesCheckERR(module, set_tabsize(size), "set_tabsize"); } -#endif +#endif /* HAVE_CURSES_SET_TABSIZE */ /*[clinic input] _curses.intrflush @@ -5075,10 +5081,8 @@ static PyMethodDef cursesmodule_methods[] = { _CURSES_RESIZETERM_METHODDEF _CURSES_RESIZE_TERM_METHODDEF _CURSES_SAVETTY_METHODDEF -#if defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102 _CURSES_GET_ESCDELAY_METHODDEF _CURSES_SET_ESCDELAY_METHODDEF -#endif _CURSES_GET_TABSIZE_METHODDEF _CURSES_SET_TABSIZE_METHODDEF _CURSES_SETSYX_METHODDEF diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 18c1a3229e93..d433e9cfc0cf 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -2792,7 +2792,7 @@ exit: return return_value; } -#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) +#if defined(HAVE_CURSES_ESCDELAY) PyDoc_STRVAR(_curses_get_escdelay__doc__, "get_escdelay($module, /)\n" @@ -2816,9 +2816,9 @@ _curses_get_escdelay(PyObject *module, PyObject *Py_UNUSED(ignored)) return _curses_get_escdelay_impl(module); } -#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ +#endif /* defined(HAVE_CURSES_ESCDELAY) */ -#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) +#if defined(HAVE_CURSES_SET_ESCDELAY) PyDoc_STRVAR(_curses_set_escdelay__doc__, "set_escdelay($module, ms, /)\n" @@ -2855,9 +2855,9 @@ exit: return return_value; } -#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ +#endif /* defined(HAVE_CURSES_SET_ESCDELAY) */ -#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) +#if defined(HAVE_CURSES_TABSIZE) PyDoc_STRVAR(_curses_get_tabsize__doc__, "get_tabsize($module, /)\n" @@ -2880,9 +2880,9 @@ _curses_get_tabsize(PyObject *module, PyObject *Py_UNUSED(ignored)) return _curses_get_tabsize_impl(module); } -#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ +#endif /* defined(HAVE_CURSES_TABSIZE) */ -#if (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) +#if defined(HAVE_CURSES_SET_TABSIZE) PyDoc_STRVAR(_curses_set_tabsize__doc__, "set_tabsize($module, size, /)\n" @@ -2918,7 +2918,7 @@ exit: return return_value; } -#endif /* (defined(NCURSES_EXT_FUNCS) && NCURSES_EXT_FUNCS >= 20081102) */ +#endif /* defined(HAVE_CURSES_SET_TABSIZE) */ PyDoc_STRVAR(_curses_intrflush__doc__, "intrflush($module, flag, /)\n" @@ -4471,4 +4471,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF #define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=e0fb3129157f3af8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=728a704064bc8b85 input=a9049054013a1b77]*/ diff --git a/configure b/configure index c92119cb5e2b..dac448e91f18 100755 --- a/configure +++ b/configure @@ -29070,6 +29070,8 @@ fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for curses function is_pad" >&5 printf %s "checking for curses function is_pad... " >&6; } if test ${ac_cv_lib_curses_is_pad+y} @@ -29728,6 +29730,242 @@ fi + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for curses function set_escdelay" >&5 +printf %s "checking for curses function set_escdelay... " >&6; } +if test ${ac_cv_lib_curses_set_escdelay+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define NCURSES_OPAQUE 0 +#if defined(HAVE_NCURSESW_NCURSES_H) +# include +#elif defined(HAVE_NCURSESW_CURSES_H) +# include +#elif defined(HAVE_NCURSES_NCURSES_H) +# include +#elif defined(HAVE_NCURSES_CURSES_H) +# include +#elif defined(HAVE_NCURSES_H) +# include +#elif defined(HAVE_CURSES_H) +# include +#endif + +int +main (void) +{ + + #ifndef set_escdelay + void *x=set_escdelay + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_lib_curses_set_escdelay=yes +else case e in #( + e) ac_cv_lib_curses_set_escdelay=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_set_escdelay" >&5 +printf "%s\n" "$ac_cv_lib_curses_set_escdelay" >&6; } + if test "x$ac_cv_lib_curses_set_escdelay" = xyes +then : + +printf "%s\n" "#define HAVE_CURSES_SET_ESCDELAY 1" >>confdefs.h + +fi + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for curses function set_tabsize" >&5 +printf %s "checking for curses function set_tabsize... " >&6; } +if test ${ac_cv_lib_curses_set_tabsize+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define NCURSES_OPAQUE 0 +#if defined(HAVE_NCURSESW_NCURSES_H) +# include +#elif defined(HAVE_NCURSESW_CURSES_H) +# include +#elif defined(HAVE_NCURSES_NCURSES_H) +# include +#elif defined(HAVE_NCURSES_CURSES_H) +# include +#elif defined(HAVE_NCURSES_H) +# include +#elif defined(HAVE_CURSES_H) +# include +#endif + +int +main (void) +{ + + #ifndef set_tabsize + void *x=set_tabsize + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_lib_curses_set_tabsize=yes +else case e in #( + e) ac_cv_lib_curses_set_tabsize=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_set_tabsize" >&5 +printf "%s\n" "$ac_cv_lib_curses_set_tabsize" >&6; } + if test "x$ac_cv_lib_curses_set_tabsize" = xyes +then : + +printf "%s\n" "#define HAVE_CURSES_SET_TABSIZE 1" >>confdefs.h + +fi + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for curses variable ESCDELAY" >&5 +printf %s "checking for curses variable ESCDELAY... " >&6; } +if test ${ac_cv_lib_curses_ESCDELAY+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define NCURSES_OPAQUE 0 +#if defined(HAVE_NCURSESW_NCURSES_H) +# include +#elif defined(HAVE_NCURSESW_CURSES_H) +# include +#elif defined(HAVE_NCURSES_NCURSES_H) +# include +#elif defined(HAVE_NCURSES_CURSES_H) +# include +#elif defined(HAVE_NCURSES_H) +# include +#elif defined(HAVE_CURSES_H) +# include +#endif + +int +main (void) +{ + + int x = ESCDELAY; (void)x; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_lib_curses_ESCDELAY=yes +else case e in #( + e) ac_cv_lib_curses_ESCDELAY=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_ESCDELAY" >&5 +printf "%s\n" "$ac_cv_lib_curses_ESCDELAY" >&6; } + if test "x$ac_cv_lib_curses_ESCDELAY" = xyes +then : + +printf "%s\n" "#define HAVE_CURSES_ESCDELAY 1" >>confdefs.h + +fi + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for curses variable TABSIZE" >&5 +printf %s "checking for curses variable TABSIZE... " >&6; } +if test ${ac_cv_lib_curses_TABSIZE+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define NCURSES_OPAQUE 0 +#if defined(HAVE_NCURSESW_NCURSES_H) +# include +#elif defined(HAVE_NCURSESW_CURSES_H) +# include +#elif defined(HAVE_NCURSES_NCURSES_H) +# include +#elif defined(HAVE_NCURSES_CURSES_H) +# include +#elif defined(HAVE_NCURSES_H) +# include +#elif defined(HAVE_CURSES_H) +# include +#endif + +int +main (void) +{ + + int x = TABSIZE; (void)x; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_lib_curses_TABSIZE=yes +else case e in #( + e) ac_cv_lib_curses_TABSIZE=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_TABSIZE" >&5 +printf "%s\n" "$ac_cv_lib_curses_TABSIZE" >&6; } + if test "x$ac_cv_lib_curses_TABSIZE" = xyes +then : + +printf "%s\n" "#define HAVE_CURSES_TABSIZE 1" >>confdefs.h + +fi + + + CPPFLAGS=$ac_save_cppflags fi diff --git a/configure.ac b/configure.ac index b23b047a12eb..d4a3bd417935 100644 --- a/configure.ac +++ b/configure.ac @@ -7047,6 +7047,30 @@ AC_DEFUN([PY_CHECK_CURSES_FUNC], AS_VAR_POPDEF([py_define]) ]) +dnl PY_CHECK_CURSES_VAR(VARIABLE) +dnl Like PY_CHECK_CURSES_FUNC, but for an integer variable (or macro), such as +dnl ESCDELAY, which a function probe cannot detect. +AC_DEFUN([PY_CHECK_CURSES_VAR], +[ AS_VAR_PUSHDEF([py_var], [ac_cv_lib_curses_$1]) + AS_VAR_PUSHDEF([py_define], [HAVE_CURSES_]m4_toupper($1)) + AC_CACHE_CHECK( + [for curses variable $1], + [py_var], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM(_CURSES_INCLUDES, [ + int x = $1; (void)x; + ])], + [AS_VAR_SET([py_var], [yes])], + [AS_VAR_SET([py_var], [no])])] + ) + AS_VAR_IF( + [py_var], + [yes], + [AC_DEFINE([py_define], [1], [Define if you have the '$1' variable.])]) + AS_VAR_POPDEF([py_var]) + AS_VAR_POPDEF([py_define]) +]) + PY_CHECK_CURSES_FUNC([is_pad]) PY_CHECK_CURSES_FUNC([is_term_resized]) PY_CHECK_CURSES_FUNC([resize_term]) @@ -7058,6 +7082,10 @@ PY_CHECK_CURSES_FUNC([filter]) PY_CHECK_CURSES_FUNC([has_key]) PY_CHECK_CURSES_FUNC([typeahead]) PY_CHECK_CURSES_FUNC([use_env]) +PY_CHECK_CURSES_FUNC([set_escdelay]) +PY_CHECK_CURSES_FUNC([set_tabsize]) +PY_CHECK_CURSES_VAR([ESCDELAY]) +PY_CHECK_CURSES_VAR([TABSIZE]) CPPFLAGS=$ac_save_cppflags ])dnl have_curses != no ])dnl save env diff --git a/pyconfig.h.in b/pyconfig.h.in index 3a45671ed5da..202b49cd22a2 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -186,6 +186,9 @@ /* Define if you have the 'ctermid_r' function. */ #undef HAVE_CTERMID_R +/* Define if you have the 'ESCDELAY' variable. */ +#undef HAVE_CURSES_ESCDELAY + /* Define if you have the 'filter' function. */ #undef HAVE_CURSES_FILTER @@ -210,9 +213,18 @@ /* Define if you have the 'resize_term' function. */ #undef HAVE_CURSES_RESIZE_TERM +/* Define if you have the 'set_escdelay' function. */ +#undef HAVE_CURSES_SET_ESCDELAY + +/* Define if you have the 'set_tabsize' function. */ +#undef HAVE_CURSES_SET_TABSIZE + /* Define if you have the 'syncok' function. */ #undef HAVE_CURSES_SYNCOK +/* Define if you have the 'TABSIZE' variable. */ +#undef HAVE_CURSES_TABSIZE + /* Define if you have the 'typeahead' function. */ #undef HAVE_CURSES_TYPEAHEAD