diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-23-21-34-34.bpo-43908.YSSVMZ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-23-21-34-34.bpo-43908.YSSVMZ.rst new file mode 100644 index 0000000000..bd82fe2f75 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-04-23-21-34-34.bpo-43908.YSSVMZ.rst @@ -0,0 +1 @@ +Apply :const:`Py_TPFLAGS_IMMUTABLETYPE` to all built-in types. Patch by Erlend E. Aasland. diff --git a/Modules/_abc.c b/Modules/_abc.c index 0ddc2abeee..e058983100 100644 --- a/Modules/_abc.c +++ b/Modules/_abc.c @@ -109,7 +109,7 @@ static PyType_Slot _abc_data_type_spec_slots[] = { static PyType_Spec _abc_data_type_spec = { .name = "_abc._abc_data", .basicsize = sizeof(_abc_data), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = _abc_data_type_spec_slots, }; diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index bfcdac6924..ad133529a0 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -404,7 +404,7 @@ static PyType_Spec bz2_compressor_type_spec = { // bz2_compressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = bz2_compressor_type_slots, }; @@ -755,7 +755,7 @@ static PyType_Spec bz2_decompressor_type_spec = { // bz2_decompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = bz2_decompressor_type_slots, }; diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c index 94caf8c93b..b1bdaddf01 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_IMMUTABLETYPE, .slots = PyCursesPanel_Type_slots }; diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 97772a04d0..5184a88386 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -414,7 +414,7 @@ static PyType_Spec dbmtype_spec = { // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = dbmtype_spec_slots, }; diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index eea542e18c..11e813a03f 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -480,7 +480,7 @@ static PyType_Slot partial_type_slots[] = { static PyType_Spec partial_type_spec = { .name = "functools.partial", .basicsize = sizeof(partialobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL, .slots = partial_type_slots }; @@ -546,7 +546,7 @@ static PyType_Slot keyobject_type_slots[] = { static PyType_Spec keyobject_type_spec = { .name = "functools.KeyWrapper", .basicsize = sizeof(keyobject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = keyobject_type_slots }; @@ -766,7 +766,7 @@ static PyType_Slot lru_list_elem_type_slots[] = { static PyType_Spec lru_list_elem_type_spec = { .name = "functools._lru_list_elem", .basicsize = sizeof(lru_list_elem), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = lru_list_elem_type_slots }; @@ -1399,7 +1399,7 @@ static PyType_Slot lru_cache_type_slots[] = { static PyType_Spec lru_cache_type_spec = { .name = "functools._lru_cache_wrapper", .basicsize = sizeof(lru_cache_object), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_METHOD_DESCRIPTOR, .slots = lru_cache_type_slots }; diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index 9e843acbaa..8ac40df4cd 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -570,7 +570,7 @@ static PyType_Spec gdbmtype_spec = { // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = gdbmtype_spec_slots, }; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 870ee89fda..555281dc29 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -598,7 +598,7 @@ static PyType_Spec EVPtype_spec = { "_hashlib.HASH", /*tp_name*/ sizeof(EVPobject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, EVPtype_slots }; @@ -748,7 +748,7 @@ static PyType_Spec EVPXOFtype_spec = { "_hashlib.HASHXOF", /*tp_name*/ sizeof(EVPobject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, EVPXOFtype_slots }; @@ -1741,7 +1741,7 @@ static PyType_Slot HMACtype_slots[] = { PyType_Spec HMACtype_spec = { "_hashlib.HMAC", /* name */ sizeof(HMACobject), /* basicsize */ - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = HMACtype_slots, }; diff --git a/Modules/_json.c b/Modules/_json.c index e10f83c96c..4158288f45 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1228,7 +1228,7 @@ static PyType_Spec PyScannerType_spec = { .name = "_json.Scanner", .basicsize = sizeof(PyScannerObject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = PyScannerType_slots, }; @@ -1787,7 +1787,7 @@ static PyType_Spec PyEncoderType_spec = { .name = "_json.Encoder", .basicsize = sizeof(PyEncoderObject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = PyEncoderType_slots }; diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c index c32699cb8a..8ba3b7c7dc 100644 --- a/Modules/_lsprof.c +++ b/Modules/_lsprof.c @@ -807,7 +807,7 @@ static PyType_Slot _lsprof_profiler_type_spec_slots[] = { static PyType_Spec _lsprof_profiler_type_spec = { .name = "_lsprof.Profiler", .basicsize = sizeof(ProfilerObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = _lsprof_profiler_type_spec_slots, }; diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index b01f630009..e91f27dc22 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -883,7 +883,7 @@ static PyType_Spec lzma_compressor_type_spec = { // lzma_compressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = lzma_compressor_type_slots, }; @@ -1341,7 +1341,7 @@ static PyType_Spec lzma_decompressor_type_spec = { // lzma_decompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag // which prevents to create a subclass. // So calling PyType_GetModuleState() in this file is always safe. - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = lzma_decompressor_type_slots, }; diff --git a/Modules/_operator.c b/Modules/_operator.c index f55c2f1d1f..b5f24a72e5 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -1124,7 +1124,7 @@ static PyType_Spec itemgetter_type_spec = { .name = "operator.itemgetter", .basicsize = sizeof(itemgetterobject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = itemgetter_type_slots, }; @@ -1446,7 +1446,7 @@ static PyType_Spec attrgetter_type_spec = { .name = "operator.attrgetter", .basicsize = sizeof(attrgetterobject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = attrgetter_type_slots, }; @@ -1691,7 +1691,7 @@ static PyType_Spec methodcaller_type_spec = { .name = "operator.methodcaller", .basicsize = sizeof(methodcallerobject), .itemsize = 0, - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = methodcaller_type_slots, }; diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index c27fb1a001..9f0529c159 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -371,7 +371,7 @@ static PyType_Slot simplequeue_slots[] = { static PyType_Spec simplequeue_spec = { .name = "_queue.SimpleQueue", .basicsize = sizeof(simplequeueobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = simplequeue_slots, }; diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index cae49a009c..828ffc9a5b 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -575,7 +575,7 @@ static PyType_Spec Random_Type_spec = { "_random.Random", sizeof(RandomObject), 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, Random_Type_slots }; diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 8da0a64a3f..e762c0c298 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -267,7 +267,7 @@ static PyType_Slot node_slots[] = { static PyType_Spec node_spec = { .name = MODULE_NAME ".Node", .basicsize = sizeof(pysqlite_Node), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = node_slots, }; PyTypeObject *pysqlite_NodeType = NULL; @@ -291,7 +291,7 @@ static PyType_Slot cache_slots[] = { static PyType_Spec cache_spec = { .name = MODULE_NAME ".Cache", .basicsize = sizeof(pysqlite_Cache), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = cache_slots, }; PyTypeObject *pysqlite_CacheType = NULL; diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 150291cb72..7bd948445c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1906,7 +1906,7 @@ static PyType_Slot connection_slots[] = { static PyType_Spec connection_spec = { .name = MODULE_NAME ".Connection", .basicsize = sizeof(pysqlite_Connection), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = connection_slots, }; diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 60dfc7dce8..70d2b18f10 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -1020,7 +1020,7 @@ static PyType_Slot cursor_slots[] = { static PyType_Spec cursor_spec = { .name = MODULE_NAME ".Cursor", .basicsize = sizeof(pysqlite_Cursor), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = cursor_slots, }; diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 7d2d7ade59..0ff63a8587 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -49,7 +49,7 @@ static PyType_Slot type_slots[] = { static PyType_Spec type_spec = { .name = MODULE_NAME ".PrepareProtocol", .basicsize = sizeof(pysqlite_PrepareProtocol), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = type_slots, }; diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index f9dfcbd5d6..d969d6a746 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -237,7 +237,7 @@ static PyType_Slot row_slots[] = { static PyType_Spec row_spec = { .name = MODULE_NAME ".Row", .basicsize = sizeof(pysqlite_Row), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = row_slots, }; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 57026270e1..4a171b9d62 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -475,7 +475,7 @@ static PyType_Slot stmt_slots[] = { static PyType_Spec stmt_spec = { .name = MODULE_NAME ".Statement", .basicsize = sizeof(pysqlite_Statement), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = stmt_slots, }; PyTypeObject *pysqlite_StatementType = NULL; diff --git a/Modules/_sre.c b/Modules/_sre.c index d4bfff6e84..b2aba56c9e 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -2690,7 +2690,7 @@ static PyType_Spec pattern_spec = { .name = "re.Pattern", .basicsize = sizeof(PatternObject), .itemsize = sizeof(SRE_CODE), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = pattern_slots, }; @@ -2755,7 +2755,7 @@ static PyType_Spec match_spec = { .name = "re.Match", .basicsize = sizeof(MatchObject), .itemsize = sizeof(Py_ssize_t), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = match_slots, }; @@ -2781,7 +2781,7 @@ static PyType_Slot scanner_slots[] = { static PyType_Spec scanner_spec = { .name = "_" SRE_MODULE ".SRE_Scanner", .basicsize = sizeof(ScannerObject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = scanner_slots, }; diff --git a/Modules/_ssl.c b/Modules/_ssl.c index e28c128678..14abf045f5 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -425,7 +425,7 @@ static PyType_Spec sslerror_type_spec = { "ssl.SSLError", sizeof(PyOSErrorObject), 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, sslerror_type_slots }; @@ -2825,7 +2825,7 @@ static PyType_Spec PySSLSocket_spec = { "_ssl._SSLSocket", sizeof(PySSLSocket), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, PySSLSocket_slots, }; @@ -4533,7 +4533,7 @@ static PyType_Spec PySSLContext_spec = { "_ssl._SSLContext", sizeof(PySSLContext), 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, PySSLContext_slots, }; @@ -4739,7 +4739,7 @@ static PyType_Spec PySSLMemoryBIO_spec = { "_ssl.MemoryBIO", sizeof(PySSLMemoryBIO), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, PySSLMemoryBIO_slots, }; @@ -4914,7 +4914,7 @@ static PyType_Spec PySSLSession_spec = { "_ssl.SSLSession", sizeof(PySSLSession), 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, PySSLSession_slots, }; diff --git a/Modules/_struct.c b/Modules/_struct.c index 30ad9f2b79..07c6192b84 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1724,7 +1724,7 @@ static PyType_Spec unpackiter_type_spec = { "_struct.unpack_iterator", sizeof(unpackiterobject), 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, unpackiter_type_slots }; @@ -2093,7 +2093,7 @@ static PyType_Spec PyStructType_spec = { "_struct.Struct", sizeof(PyStructObject), 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, PyStructType_slots }; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 7feb0b8a1f..22f13dc9d9 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -312,7 +312,7 @@ static PyType_Slot lock_type_slots[] = { static PyType_Spec lock_type_spec = { .name = "_thread.lock", .basicsize = sizeof(lockobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = lock_type_slots, }; @@ -584,7 +584,7 @@ static PyType_Slot rlock_type_slots[] = { static PyType_Spec rlock_type_spec = { .name = "_thread.RLock", .basicsize = sizeof(rlockobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = rlock_type_slots, }; @@ -683,7 +683,7 @@ static PyType_Slot local_dummy_type_slots[] = { static PyType_Spec local_dummy_type_spec = { .name = "_thread._localdummy", .basicsize = sizeof(localdummyobject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = local_dummy_type_slots, }; @@ -967,7 +967,7 @@ static PyType_Slot local_type_slots[] = { static PyType_Spec local_type_spec = { .name = "_thread._local", .basicsize = sizeof(localobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = local_type_slots, }; diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 46d6a6e095..078d507a4e 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_IMMUTABLETYPE, 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_IMMUTABLETYPE, 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_IMMUTABLETYPE, Tkapp_Type_slots, }; diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 9d5a45adac..02d806799a 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -331,7 +331,7 @@ static PyType_Slot winapi_overlapped_type_slots[] = { static PyType_Spec winapi_overlapped_type_spec = { .name = "_winapi.Overlapped", .basicsize = sizeof(OverlappedObject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = winapi_overlapped_type_slots, }; diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index f532678952..3c098f4a88 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2985,7 +2985,7 @@ static PyType_Slot arrayiter_slots[] = { static PyType_Spec arrayiter_spec = { .name = "array.arrayiterator", .basicsize = sizeof(arrayiterobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = arrayiter_slots, }; diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index 5070c983d4..8d62269803 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -748,7 +748,7 @@ static PyType_Slot multibytecodec_slots[] = { static PyType_Spec multibytecodec_spec = { .name = MODULE_NAME ".MultibyteCodec", .basicsize = sizeof(MultibyteCodecObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = multibytecodec_slots, }; @@ -1110,7 +1110,7 @@ static PyType_Slot encoder_slots[] = { static PyType_Spec encoder_spec = { .name = MODULE_NAME ".MultibyteIncrementalEncoder", .basicsize = sizeof(MultibyteIncrementalEncoderObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, .slots = encoder_slots, }; @@ -1383,7 +1383,7 @@ static PyType_Slot decoder_slots[] = { static PyType_Spec decoder_spec = { .name = MODULE_NAME ".MultibyteIncrementalDecoder", .basicsize = sizeof(MultibyteIncrementalDecoderObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, .slots = decoder_slots, }; @@ -1704,7 +1704,7 @@ static PyType_Slot reader_slots[] = { static PyType_Spec reader_spec = { .name = MODULE_NAME ".MultibyteStreamReader", .basicsize = sizeof(MultibyteStreamReaderObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, .slots = reader_slots, }; @@ -1924,7 +1924,7 @@ static PyType_Slot writer_slots[] = { static PyType_Spec writer_spec = { .name = MODULE_NAME ".MultibyteStreamWriter", .basicsize = sizeof(MultibyteStreamWriterObject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, .slots = writer_slots, }; diff --git a/Modules/md5module.c b/Modules/md5module.c index b2e65a0a5f..86b131610e 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -484,7 +484,7 @@ static PyType_Slot md5_type_slots[] = { static PyType_Spec md5_type_spec = { .name = "_md5.md5", .basicsize = sizeof(MD5object), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = md5_type_slots }; diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index 1e66962d37..9f4091c762 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1114,7 +1114,7 @@ static PyType_Slot mmap_object_slots[] = { static PyType_Spec mmap_object_spec = { .name = "mmap.mmap", .basicsize = sizeof(mmap_object), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE, .slots = mmap_object_slots, }; diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 38dd98f084..81fb05896a 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -1876,7 +1876,7 @@ static PyType_Slot overlapped_type_slots[] = { static PyType_Spec overlapped_type_spec = { .name = "_overlapped.Overlapped", .basicsize = sizeof(OverlappedObject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = overlapped_type_slots }; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 85e1e6976d..44c499eb21 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -13776,7 +13776,7 @@ static PyType_Spec DirEntryType_spec = { MODNAME ".DirEntry", sizeof(DirEntry), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, DirEntryType_slots }; @@ -14211,7 +14211,7 @@ static PyType_Spec ScandirIteratorType_spec = { 0, // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance. - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_FINALIZE, ScandirIteratorType_slots }; diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index a13d340a3e..4047d627a5 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1506,7 +1506,7 @@ static PyType_Slot _xml_parse_type_spec_slots[] = { static PyType_Spec _xml_parse_type_spec = { .name = "pyexpat.xmlparser", .basicsize = sizeof(xmlparseobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, .slots = _xml_parse_type_spec_slots, }; diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index f80da58954..3a975e0636 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -1146,7 +1146,7 @@ static PyType_Spec devpoll_Type_spec = { "select.devpoll", sizeof(devpollObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, devpoll_Type_slots }; @@ -1920,7 +1920,7 @@ static PyType_Spec kqueue_event_Type_spec = { "select.kevent", sizeof(kqueue_event_Object), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, kqueue_event_Type_slots }; @@ -2283,7 +2283,7 @@ static PyType_Spec poll_Type_spec = { "select.poll", sizeof(pollObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, poll_Type_slots }; @@ -2332,7 +2332,7 @@ static PyType_Spec pyEpoll_Type_spec = { "select.epoll", sizeof(pyEpoll_Object), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, pyEpoll_Type_slots }; @@ -2361,7 +2361,7 @@ static PyType_Spec kqueue_queue_Type_spec = { "select.kqueue", sizeof(kqueue_queue_Object), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, kqueue_queue_Type_slots }; diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 7126db93b1..4e5beac28e 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -462,7 +462,7 @@ static PyType_Slot sha1_type_slots[] = { static PyType_Spec sha1_type_spec = { .name = "_sha1.sha1", .basicsize = sizeof(SHA1object), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = sha1_type_slots }; diff --git a/Modules/sha256module.c b/Modules/sha256module.c index b90e5df782..9121f7365c 100644 --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -544,14 +544,14 @@ static PyType_Slot sha256_types_slots[] = { static PyType_Spec sha224_type_spec = { .name = "_sha256.sha224", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = sha256_types_slots }; static PyType_Spec sha256_type_spec = { .name = "_sha256.sha256", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = sha256_types_slots }; diff --git a/Modules/sha512module.c b/Modules/sha512module.c index 0d8f51e5ae..b82e6938bf 100644 --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -602,7 +602,7 @@ static PyType_Slot sha512_sha384_type_slots[] = { static PyType_Spec sha512_sha384_type_spec = { .name = "_sha512.sha384", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = sha512_sha384_type_slots }; @@ -619,7 +619,7 @@ static PyType_Slot sha512_sha512_type_slots[] = { static PyType_Spec sha512_sha512_type_spec = { .name = "_sha512.sha512", .basicsize = sizeof(SHAobject), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = sha512_sha512_type_slots }; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index aebae7da57..e1786bad3a 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -1454,7 +1454,7 @@ static PyType_Slot ucd_type_slots[] = { static PyType_Spec ucd_type_spec = { .name = "unicodedata.UCD", .basicsize = sizeof(PreviousDBVersion), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, .slots = ucd_type_slots }; diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index a537087d19..d2e586bcf0 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1337,7 +1337,7 @@ static PyType_Spec Comptype_spec = { "zlib.Compress", sizeof(compobject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, Comptype_slots }; @@ -1352,7 +1352,7 @@ static PyType_Spec Decomptype_spec = { "zlib.Decompress", sizeof(compobject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, Decomptype_slots }; diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 9efe3aac2e1c9..10b8b2584aef7 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1177,6 +1177,17 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. versionadded:: 3.10 + .. data:: Py_TPFLAGS_IMMUTABLETYPE + + This bit is set for type objects that are immutable. Static types are + immutable by default; setting this flag has no effect for static types. + + **Inheritance:** + + This flag is never inherited. + + .. versionadded:: 3.10 + .. c:member:: const char* PyTypeObject.tp_doc diff --git a/Include/object.h b/Include/object.h index 695f01564282c..a239063e3965c 100644 --- a/Include/object.h +++ b/Include/object.h @@ -320,6 +320,9 @@ Code can use PyType_HasFeature(type_ob, flag_value) to test whether the given type object has a specified feature. */ +/* Set if the type object is immutable */ +#define Py_TPFLAGS_IMMUTABLETYPE (1UL << 8) + /* Set if the type object is dynamically allocated */ #define Py_TPFLAGS_HEAPTYPE (1UL << 9) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index bdcd1254b304f..d419d59ad2d50 100644 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -50,6 +50,10 @@ def test_empty(self): a += a self.assertEqual(len(a), 0) + def test_immutable(self): + with self.assertRaises(TypeError): + array.array.foo = 1 + # Machine format codes. # diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst new file mode 100644 index 0000000000000..1558498329efd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst @@ -0,0 +1,3 @@ +Introduce :const:`Py_TPFLAGS_IMMUTABLETYPE` for immutable type objects and +apply it to types that lately have been converted to heap types. Patch by +Erlend E. Aasland. diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index fb9ebbe9f4870..b98358fa5d8a4 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2846,7 +2846,7 @@ static PyType_Slot array_slots[] = { static PyType_Spec array_spec = { .name = "array.array", .basicsize = sizeof(arrayobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE, .slots = array_slots, }; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a957c832b90bd..cf6cf0fc25f45 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3859,7 +3859,7 @@ static int type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { int res; - if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { PyErr_Format( PyExc_TypeError, "can't set attributes of built-in/extension type '%s'", @@ -6213,6 +6213,10 @@ PyType_Ready(PyTypeObject *type) type->tp_flags |= Py_TPFLAGS_READYING; + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE; + } + if (type_ready(type) < 0) { type->tp_flags &= ~Py_TPFLAGS_READYING; return -1;