[Python-checkins] bpo-46417: _curses uses PyStructSequence_NewType() (GH-30736)

vstinner webhook-mailer at python.org
Thu Jan 20 21:30:30 EST 2022


https://github.com/python/cpython/commit/1781d55eb34f94029e50970232635fc5082378cb
commit: 1781d55eb34f94029e50970232635fc5082378cb
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-01-21T03:30:20+01:00
summary:

bpo-46417: _curses uses PyStructSequence_NewType() (GH-30736)

The _curses module now creates its ncurses_version type as a heap
type using PyStructSequence_NewType(), rather than using a static
type.

* Move _PyStructSequence_FiniType() definition to pycore_structseq.h.
* test.pythoninfo: log curses.ncurses_version.

files:
M Include/internal/pycore_structseq.h
M Include/structseq.h
M Lib/test/pythoninfo.py
M Modules/_cursesmodule.c
M Objects/floatobject.c
M Objects/longobject.c
M Objects/structseq.c
M Python/errors.c
M Python/sysmodule.c
M Python/thread.c

diff --git a/Include/internal/pycore_structseq.h b/Include/internal/pycore_structseq.h
index 3a61cb9a12608..c0323bbea8991 100644
--- a/Include/internal/pycore_structseq.h
+++ b/Include/internal/pycore_structseq.h
@@ -16,11 +16,16 @@ extern PyStatus _PyStructSequence_InitState(PyInterpreterState *);
 
 /* other API */
 
+PyAPI_FUNC(PyTypeObject *) _PyStructSequence_NewType(
+    PyStructSequence_Desc *desc,
+    unsigned long tp_flags);
+
 PyAPI_FUNC(int) _PyStructSequence_InitType(
     PyTypeObject *type,
     PyStructSequence_Desc *desc,
     unsigned long tp_flags);
 
+extern void _PyStructSequence_FiniType(PyTypeObject *type);
 
 #ifdef __cplusplus
 }
diff --git a/Include/structseq.h b/Include/structseq.h
index 8abd2443468b7..e89265a67c322 100644
--- a/Include/structseq.h
+++ b/Include/structseq.h
@@ -27,9 +27,6 @@ PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type,
 PyAPI_FUNC(int) PyStructSequence_InitType2(PyTypeObject *type,
                                            PyStructSequence_Desc *desc);
 #endif
-#ifdef Py_BUILD_CORE
-PyAPI_FUNC(void) _PyStructSequence_FiniType(PyTypeObject *type);
-#endif
 PyAPI_FUNC(PyTypeObject*) PyStructSequence_NewType(PyStructSequence_Desc *desc);
 
 PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type);
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index 39ee9e1d769f8..9d733c5721cde 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -434,6 +434,15 @@ def collect_time(info_add):
                 info_add('time.get_clock_info(%s)' % clock, clock_info)
 
 
+def collect_curses(info_add):
+    try:
+        import curses
+    except ImportError:
+        return
+
+    copy_attr(info_add, 'curses.ncurses_version', curses, 'ncurses_version')
+
+
 def collect_datetime(info_add):
     try:
         import datetime
@@ -752,6 +761,7 @@ def collect_info(info):
 
         collect_builtins,
         collect_cc,
+        collect_curses,
         collect_datetime,
         collect_decimal,
         collect_expat,
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index bf742dacf0110..423b042b90755 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -108,7 +108,7 @@ static const char PyCursesVersion[] = "2.2";
 
 #include "Python.h"
 #include "pycore_long.h"          // _PyLong_GetZero()
-#include "pycore_structseq.h"     // PyStructSequence_InitType()
+#include "pycore_structseq.h"     // _PyStructSequence_NewType()
 
 #ifdef __hpux
 #define STRICT_SYSV_CURSES
@@ -4569,8 +4569,6 @@ PyDoc_STRVAR(ncurses_version__doc__,
 \n\
 Ncurses version information as a named tuple.");
 
-static PyTypeObject NcursesVersionType;
-
 static PyStructSequence_Field ncurses_version_fields[] = {
     {"major", "Major release number"},
     {"minor", "Minor release number"},
@@ -4586,12 +4584,12 @@ static PyStructSequence_Desc ncurses_version_desc = {
 };
 
 static PyObject *
-make_ncurses_version(void)
+make_ncurses_version(PyTypeObject *type)
 {
     PyObject *ncurses_version;
     int pos = 0;
 
-    ncurses_version = PyStructSequence_New(&NcursesVersionType);
+    ncurses_version = PyStructSequence_New(type);
     if (ncurses_version == NULL) {
         return NULL;
     }
@@ -4796,14 +4794,14 @@ PyInit__curses(void)
 
 #ifdef NCURSES_VERSION
     /* ncurses_version */
-    if (NcursesVersionType.tp_name == NULL) {
-        if (_PyStructSequence_InitType(&NcursesVersionType,
-                                       &ncurses_version_desc,
-                                       Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) {
-            return NULL;
-        }
+    PyTypeObject *version_type;
+    version_type = _PyStructSequence_NewType(&ncurses_version_desc,
+                                             Py_TPFLAGS_DISALLOW_INSTANTIATION);
+    if (version_type == NULL) {
+        return NULL;
     }
-    v = make_ncurses_version();
+    v = make_ncurses_version(version_type);
+    Py_DECREF(version_type);
     if (v == NULL) {
         return NULL;
     }
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 88f25d6b8c886..68be7acaa2e72 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -12,6 +12,7 @@
 #include "pycore_object.h"        // _PyObject_Init()
 #include "pycore_pymath.h"        // _Py_ADJUST_ERANGE1()
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
+#include "pycore_structseq.h"     // _PyStructSequence_FiniType()
 
 #include <ctype.h>
 #include <float.h>
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 5aa53dd91c299..7721f40adbba6 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -9,6 +9,7 @@
 #include "pycore_object.h"        // _PyObject_InitVar()
 #include "pycore_pystate.h"       // _Py_IsMainInterpreter()
 #include "pycore_runtime.h"       // _PY_NSMALLPOSINTS
+#include "pycore_structseq.h"     // _PyStructSequence_FiniType()
 
 #include <ctype.h>
 #include <float.h>
diff --git a/Objects/structseq.c b/Objects/structseq.c
index f8bf9477f2848..dfefae8928eb6 100644
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -563,7 +563,7 @@ _PyStructSequence_FiniType(PyTypeObject *type)
 
 
 PyTypeObject *
-PyStructSequence_NewType(PyStructSequence_Desc *desc)
+_PyStructSequence_NewType(PyStructSequence_Desc *desc, unsigned long tp_flags)
 {
     PyMemberDef *members;
     PyTypeObject *type;
@@ -596,7 +596,7 @@ PyStructSequence_NewType(PyStructSequence_Desc *desc)
     spec.name = desc->name;
     spec.basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
     spec.itemsize = sizeof(PyObject *);
-    spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC;
+    spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags;
     spec.slots = slots;
 
     type = (PyTypeObject *)PyType_FromSpecWithBases(&spec, (PyObject *)&PyTuple_Type);
@@ -615,6 +615,13 @@ PyStructSequence_NewType(PyStructSequence_Desc *desc)
 }
 
 
+PyTypeObject *
+PyStructSequence_NewType(PyStructSequence_Desc *desc)
+{
+    return _PyStructSequence_NewType(desc, 0);
+}
+
+
 /* runtime lifecycle */
 
 PyStatus _PyStructSequence_InitState(PyInterpreterState *interp)
diff --git a/Python/errors.c b/Python/errors.c
index 211881ca5eb6c..023234974c47d 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -6,6 +6,7 @@
 #include "pycore_initconfig.h"    // _PyStatus_ERR()
 #include "pycore_pyerrors.h"      // _PyErr_Format()
 #include "pycore_pystate.h"       // _PyThreadState_GET()
+#include "pycore_structseq.h"     // _PyStructSequence_FiniType()
 #include "pycore_sysmodule.h"     // _PySys_Audit()
 #include "pycore_traceback.h"     // _PyTraceBack_FromFrame()
 
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 515994f049086..7597ea2ea9e49 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -27,7 +27,7 @@ Data members:
 #include "pycore_pylifecycle.h"   // _PyErr_WriteUnraisableDefaultHook()
 #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
 #include "pycore_pystate.h"       // _PyThreadState_GET()
-#include "pycore_structseq.h"     // PyStructSequence_InitType()
+#include "pycore_structseq.h"     // _PyStructSequence_InitType()
 #include "pycore_tuple.h"         // _PyTuple_FromArray()
 
 #include "code.h"
diff --git a/Python/thread.c b/Python/thread.c
index c2457c4f8fe83..c6b16251a05b6 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -6,7 +6,8 @@
    Stuff shared by all thread_*.h files is collected here. */
 
 #include "Python.h"
-#include "pycore_pystate.h"   // _PyInterpreterState_GET()
+#include "pycore_pystate.h"       // _PyInterpreterState_GET()
+#include "pycore_structseq.h"     // _PyStructSequence_FiniType()
 
 #ifndef _POSIX_THREADS
 /* This means pthreads are not implemented in libc headers, hence the macro



More information about the Python-checkins mailing list