Thanks to visit codestin.com
Credit goes to github.com

Skip to content

gh-87175: Port curses capi pointer array to a struct. #24304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,12 @@ New Features

(Contributed by Eddie Elizondo in :gh:`84436`.)

* Convert the ``PyCurses_API`` C API (``_curses._C_API`` capsule) from a pointer
array to a structure(``PyCurses_C_API``) in pycore_curses.h. ``PyCursesWindow_Type``,
``PyCursesSetupTermCalled``, ``PyCursesInitialised``, ``PyCursesInitialisedColor``
be moved into internal APIs and the public API will be deprecated in 3.14.
(Contributed by Hai Shi in :gh:`87175`).

Porting to Python 3.12
----------------------

Expand Down
46 changes: 46 additions & 0 deletions Include/internal/pycore_curses.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#ifndef Py_INTERNAL_CURSES_H
#define Py_INTERNAL_CURSES_H

#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
PyTypeObject *window_type;
int (*setup_term_called)(void);
int (*initialized)(void);
int (*initialized_color)(void);
} PyCurses_CAPI;

#ifdef CURSES_MODULE
/* This section is used when compiling _cursesmodule.c */

#else
/* This section is used in modules that use the _cursesmodule API */

static PyCurses_CAPI *PyCurses_C_API;

#undef PyCursesWindow_Type
#undef PyCursesSetupTermCalled
#undef PyCursesInitialised
#undef PyCursesInitialisedColor
#define PyCursesWindow_Type (*PyCurses_C_API->window_type)
#define PyCursesSetupTermCalled {if (!PyCurses_C_API->setup_term_called()) return NULL;}
#define PyCursesInitialised {if (!PyCurses_C_API->initialized()) return NULL;}
#define PyCursesInitialisedColor {if (!PyCurses_C_API->initialized_color()) return NULL;}

#undef import_curses
#define import_curses() \
PyCurses_C_API = PyCapsule_Import(PyCurses_CAPSULE_NAME, 1);

#endif

#ifdef __cplusplus
}
#endif

#endif /* !Py_INTERNAL_CURSES_H */
3 changes: 2 additions & 1 deletion Include/py_curses.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ typedef struct {
#else
/* This section is used in modules that use the _cursesmodule API */

static void **PyCurses_API;
Py_DEPRECATED(3.14) static void **PyCurses_API;

/* Those macros will be deprecated in 3.14 and moved into internal APIs. */
#define PyCursesWindow_Type (*_PyType_CAST(PyCurses_API[0]))
#define PyCursesSetupTermCalled {if (! ((int (*)(void))PyCurses_API[1]) () ) return NULL;}
#define PyCursesInitialised {if (! ((int (*)(void))PyCurses_API[2]) () ) return NULL;}
Expand Down
1 change: 1 addition & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_compile.h \
$(srcdir)/Include/internal/pycore_condvar.h \
$(srcdir)/Include/internal/pycore_context.h \
$(srcdir)/Include/internal/pycore_curses.h \
$(srcdir)/Include/internal/pycore_dict.h \
$(srcdir)/Include/internal/pycore_dict_state.h \
$(srcdir)/Include/internal/pycore_descrobject.h \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Convert the ``PyCurses_API`` C API (``_curses._C_API`` capsule) from a pointer array to a structure(``PyCurses_C_API``) in pycore_curses.h.
``PyCursesWindow_Type``, ``PyCursesSetupTermCalled``, ``PyCursesInitialised``, ``PyCursesInitialisedColor`` be moved into internal APIs and the public API will be deprecated in 3.14.
5 changes: 5 additions & 0 deletions Modules/_curses_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ static const char PyCursesVersion[] = "2.1";

/* Includes */

#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif

#include "Python.h"

#include "py_curses.h"
#include "pycore_curses.h"

#include <panel.h>

Expand Down
20 changes: 11 additions & 9 deletions Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ static const char PyCursesVersion[] = "2.2";

#define CURSES_MODULE
#include "py_curses.h"
#include "pycore_curses.h"

#if defined(HAVE_TERM_H) || defined(__sgi)
/* For termname, longname, putp, tigetflag, tigetnum, tigetstr, tparm
Expand Down Expand Up @@ -4727,8 +4728,8 @@ static struct PyModuleDef _cursesmodule = {
static void
curses_destructor(PyObject *op)
{
void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME);
Py_DECREF(*(void **)ptr);
PyCurses_CAPI *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME);
Py_DECREF(ptr->window_type);
PyMem_Free(ptr);
}

Expand All @@ -4752,22 +4753,23 @@ PyInit__curses(void)
return NULL;
ModDict = d; /* For PyCurses_InitScr to use later */

void **PyCurses_API = PyMem_Calloc(PyCurses_API_pointers, sizeof(void *));
PyCurses_CAPI *PyCurses_API = PyMem_Malloc(sizeof(PyCurses_CAPI));
if (PyCurses_API == NULL) {
PyErr_NoMemory();
return NULL;
}
/* Initialize the C API pointer array */
PyCurses_API[0] = (void *)Py_NewRef(&PyCursesWindow_Type);
PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled;
PyCurses_API[2] = (void *)func_PyCursesInitialised;
PyCurses_API[3] = (void *)func_PyCursesInitialisedColor;
/* Initialize the C API struct */
PyCurses_API->window_type = (PyTypeObject *)Py_NewRef(
&PyCursesWindow_Type);
PyCurses_API->setup_term_called = func_PyCursesSetupTermCalled;
PyCurses_API->initialized = func_PyCursesInitialised;
PyCurses_API->initialized_color = func_PyCursesInitialisedColor;

/* Add a capsule for the C API */
c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME,
curses_destructor);
if (c_api_object == NULL) {
Py_DECREF(PyCurses_API[0]);
Py_DECREF(PyCurses_API->window_type);
PyMem_Free(PyCurses_API);
return NULL;
}
Expand Down
1 change: 1 addition & 0 deletions PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@
<ClInclude Include="..\Include\internal\pycore_compile.h" />
<ClInclude Include="..\Include\internal\pycore_condvar.h" />
<ClInclude Include="..\Include\internal\pycore_context.h" />
<ClInclude Include="..\Include\internal\pycore_curses.h" />
<ClInclude Include="..\Include\internal\pycore_descrobject.h" />
<ClInclude Include="..\Include\internal\pycore_dict.h" />
<ClInclude Include="..\Include\internal\pycore_dict_state.h" />
Expand Down
3 changes: 3 additions & 0 deletions PCbuild/pythoncore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,9 @@
<ClInclude Include="..\Include\internal\pycore_context.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_curses.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_descrobject.h">
<Filter>Include\internal</Filter>
</ClInclude>
Expand Down
1 change: 1 addition & 0 deletions Tools/c-analyzer/cpython/ignored.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ Modules/_xxtestfuzz/fuzzer.c LLVMFuzzerTestOneInput AST_LITERAL_EVAL_INITIALIZED
# XXX Fix the analyzer.

## forward/extern references
Include/internal/pycore_curses.h - PyCurses_C_API -
Include/py_curses.h - PyCurses_API -
Include/pydecimal.h - _decimal_api -
Modules/_blake2/blake2module.c - blake2b_type_spec -
Expand Down