From 3bb09947ec4837de75532e21dd4bd25db0a1f1b7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 30 Apr 2021 12:46:15 +0200 Subject: 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. --- Python/sysmodule.c | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) (limited to 'Python/sysmodule.c') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 911c2d967b0..36297ff82e1 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2810,56 +2810,35 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) /* version_info */ if (VersionInfoType.tp_name == NULL) { - if (PyStructSequence_InitType2(&VersionInfoType, - &version_info_desc) < 0) { + if (_PyStructSequence_InitType(&VersionInfoType, + &version_info_desc, + Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { goto type_init_failed; } } version_info = make_version_info(tstate); SET_SYS("version_info", version_info); - /* prevent user from creating new instances */ - VersionInfoType.tp_init = NULL; - VersionInfoType.tp_new = NULL; - res = PyDict_DelItemString(VersionInfoType.tp_dict, "__new__"); - if (res < 0 && _PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { - _PyErr_Clear(tstate); - } /* implementation */ SET_SYS("implementation", make_impl_info(version_info)); // sys.flags: updated in-place later by _PySys_UpdateConfig() if (FlagsType.tp_name == 0) { - if (PyStructSequence_InitType2(&FlagsType, &flags_desc) < 0) { + if (_PyStructSequence_InitType(&FlagsType, &flags_desc, + Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { goto type_init_failed; } } SET_SYS("flags", make_flags(tstate->interp)); - /* prevent user from creating new instances */ - FlagsType.tp_init = NULL; - FlagsType.tp_new = NULL; - res = PyDict_DelItemString(FlagsType.tp_dict, "__new__"); - if (res < 0) { - if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { - goto err_occurred; - } - _PyErr_Clear(tstate); - } #if defined(MS_WINDOWS) /* getwindowsversion */ - if (WindowsVersionType.tp_name == 0) - if (PyStructSequence_InitType2(&WindowsVersionType, - &windows_version_desc) < 0) { + if (WindowsVersionType.tp_name == 0) { + if (_PyStructSequence_InitType(&WindowsVersionType, + &windows_version_desc, + Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { goto type_init_failed; } - /* prevent user from creating new instances */ - WindowsVersionType.tp_init = NULL; - WindowsVersionType.tp_new = NULL; - assert(!_PyErr_Occurred(tstate)); - res = PyDict_DelItemString(WindowsVersionType.tp_dict, "__new__"); - if (res < 0 && _PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { - _PyErr_Clear(tstate); } #endif -- cgit v1.2.3