diff options
author | Victor Stinner <vstinner@python.org> | 2021-04-30 10:46:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-30 10:46:15 (GMT) |
commit | 3bb09947ec4837de75532e21dd4bd25db0a1f1b7 (patch) | |
tree | 46469716b18eda1c8af7c311b6187fda39a146c1 /Modules | |
parent | b73b5fb9ea08156991a065c1696e8d8cf7622482 (diff) | |
download | cpython-3bb09947ec4837de75532e21dd4bd25db0a1f1b7.zip cpython-3bb09947ec4837de75532e21dd4bd25db0a1f1b7.tar.gz cpython-3bb09947ec4837de75532e21dd4bd25db0a1f1b7.tar.bz2 |
bpo-43916: Add Py_TPFLAGS_DISALLOW_INSTANTIATION type flag (GH-25721)
Add a new Py_TPFLAGS_DISALLOW_INSTANTIATION type flag to disallow
creating type instances: set tp_new to NULL and don't create the
"__new__" key in the type dictionary.
The flag is set automatically on static types if tp_base is NULL or
&PyBaseObject_Type and tp_new is NULL.
Use the flag on the following types:
* _curses.ncurses_version type
* _curses_panel.panel
* _tkinter.Tcl_Obj
* _tkinter.tkapp
* _tkinter.tktimertoken
* _xxsubinterpretersmodule.ChannelID
* sys.flags type
* sys.getwindowsversion() type
* sys.version_info type
Update MyStr example in the C API documentation to use
Py_TPFLAGS_DISALLOW_INSTANTIATION.
Add _PyStructSequence_InitType() function to create a structseq type
with the Py_TPFLAGS_DISALLOW_INSTANTIATION flag set.
type_new() calls _PyType_CheckConsistency() at exit.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_curses_panel.c | 3 | ||||
-rw-r--r-- | Modules/_cursesmodule.c | 15 | ||||
-rw-r--r-- | Modules/_tkinter.c | 9 | ||||
-rw-r--r-- | Modules/_xxsubinterpretersmodule.c | 20 |
4 files changed, 14 insertions, 33 deletions
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c index 94caf8c..0b328f9 100644 --- a/Modules/_curses_panel.c +++ b/Modules/_curses_panel.c @@ -520,7 +520,7 @@ static PyType_Slot PyCursesPanel_Type_slots[] = { static PyType_Spec PyCursesPanel_Type_spec = { .name = "_curses_panel.panel", .basicsize = sizeof(PyCursesPanelObject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, .slots = PyCursesPanel_Type_slots }; @@ -656,7 +656,6 @@ _curses_panel_exec(PyObject *mod) if (state->PyCursesPanel_Type == NULL) { return -1; } - ((PyTypeObject *)state->PyCursesPanel_Type)->tp_new = NULL; if (PyModule_AddType(mod, state->PyCursesPanel_Type) < 0) { return -1; diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index d221cf1..bcf9ad1 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -4793,9 +4793,11 @@ PyInit__curses(void) #ifdef NCURSES_VERSION /* ncurses_version */ if (NcursesVersionType.tp_name == NULL) { - if (PyStructSequence_InitType2(&NcursesVersionType, - &ncurses_version_desc) < 0) + if (_PyStructSequence_InitType(&NcursesVersionType, + &ncurses_version_desc, + Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { return NULL; + } } v = make_ncurses_version(); if (v == NULL) { @@ -4803,15 +4805,6 @@ PyInit__curses(void) } PyDict_SetItemString(d, "ncurses_version", v); Py_DECREF(v); - - /* prevent user from creating new instances */ - NcursesVersionType.tp_init = NULL; - NcursesVersionType.tp_new = NULL; - if (PyDict_DelItemString(NcursesVersionType.tp_dict, "__new__") < 0 && - PyErr_ExceptionMatches(PyExc_KeyError)) - { - PyErr_Clear(); - } #endif /* NCURSES_VERSION */ SetDictInt("ERR", ERR); diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 46d6a6e..3a0e5de 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1002,7 +1002,7 @@ static PyType_Spec PyTclObject_Type_spec = { "_tkinter.Tcl_Obj", sizeof(PyTclObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, PyTclObject_Type_slots, }; @@ -3294,7 +3294,7 @@ static PyType_Spec Tktt_Type_spec = { "_tkinter.tktimertoken", sizeof(TkttObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, Tktt_Type_slots, }; @@ -3349,7 +3349,7 @@ static PyType_Spec Tkapp_Type_spec = { "_tkinter.tkapp", sizeof(TkappObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, Tkapp_Type_slots, }; @@ -3537,7 +3537,6 @@ PyInit__tkinter(void) Py_DECREF(m); return NULL; } - ((PyTypeObject *)o)->tp_new = NULL; if (PyModule_AddObject(m, "TkappType", o)) { Py_DECREF(o); Py_DECREF(m); @@ -3550,7 +3549,6 @@ PyInit__tkinter(void) Py_DECREF(m); return NULL; } - ((PyTypeObject *)o)->tp_new = NULL; if (PyModule_AddObject(m, "TkttType", o)) { Py_DECREF(o); Py_DECREF(m); @@ -3563,7 +3561,6 @@ PyInit__tkinter(void) Py_DECREF(m); return NULL; } - ((PyTypeObject *)o)->tp_new = NULL; if (PyModule_AddObject(m, "Tcl_Obj", o)) { Py_DECREF(o); Py_DECREF(m); diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index b94b130..9290255 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1780,7 +1780,12 @@ static PyTypeObject ChannelIDtype = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + // Use Py_TPFLAGS_DISALLOW_INSTANTIATION so the type cannot be instantiated + // from Python code. We do this because there is a strong relationship + // between channel IDs and the channel lifecycle, so this limitation avoids + // related complications. Use the _channel_id() function instead. + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_DISALLOW_INSTANTIATION, /* tp_flags */ channelid_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -1791,19 +1796,6 @@ static PyTypeObject ChannelIDtype = { 0, /* tp_methods */ 0, /* tp_members */ channelid_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - // Note that we do not set tp_new to channelid_new. Instead we - // set it to NULL, meaning it cannot be instantiated from Python - // code. We do this because there is a strong relationship between - // channel IDs and the channel lifecycle, so this limitation avoids - // related complications. - NULL, /* tp_new */ }; |