summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2024-10-25 09:12:48 (GMT)
committerGitHub <noreply@github.com>2024-10-25 09:12:48 (GMT)
commitdb96327203b09ada45f2214567f92fe4d837f82a (patch)
tree29febc64dbeff2a1ce81080519fca0437c2e54f8 /Objects
parentda8673da362a2135cd621ac619d3aced6bb55100 (diff)
downloadcpython-db96327203b09ada45f2214567f92fe4d837f82a.zip
cpython-db96327203b09ada45f2214567f92fe4d837f82a.tar.gz
cpython-db96327203b09ada45f2214567f92fe4d837f82a.tar.bz2
gh-121654: Add PyType_Freeze() function (#122457)
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c65
1 files changed, 52 insertions, 13 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 4d84382..b4a1119 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -4637,6 +4637,32 @@ check_basicsize_includes_size_and_offsets(PyTypeObject* type)
return 1;
}
+static int
+check_immutable_bases(const char *type_name, PyObject *bases, int skip_first)
+{
+ Py_ssize_t i = 0;
+ if (skip_first) {
+ // When testing the MRO, skip the type itself
+ i = 1;
+ }
+ for (; i<PyTuple_GET_SIZE(bases); i++) {
+ PyTypeObject *b = (PyTypeObject*)PyTuple_GET_ITEM(bases, i);
+ if (!b) {
+ return -1;
+ }
+ if (!_PyType_HasFeature(b, Py_TPFLAGS_IMMUTABLETYPE)) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "Creating immutable type %s from mutable base %N",
+ type_name, b
+ );
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
/* Set *dest to the offset specified by a special "__*offset__" member.
* Return 0 on success, -1 on failure.
*/
@@ -4820,19 +4846,8 @@ PyType_FromMetaclass(
* and only heap types can be mutable.)
*/
if (spec->flags & Py_TPFLAGS_IMMUTABLETYPE) {
- for (int i=0; i<PyTuple_GET_SIZE(bases); i++) {
- PyTypeObject *b = (PyTypeObject*)PyTuple_GET_ITEM(bases, i);
- if (!b) {
- goto finally;
- }
- if (!_PyType_HasFeature(b, Py_TPFLAGS_IMMUTABLETYPE)) {
- PyErr_Format(
- PyExc_TypeError,
- "Creating immutable type %s from mutable base %N",
- spec->name, b
- );
- goto finally;
- }
+ if (check_immutable_bases(spec->name, bases, 0) < 0) {
+ goto finally;
}
}
@@ -11319,6 +11334,30 @@ add_operators(PyTypeObject *type)
}
+int
+PyType_Freeze(PyTypeObject *type)
+{
+ // gh-121654: Check the __mro__ instead of __bases__
+ PyObject *mro = type_get_mro(type, NULL);
+ if (!PyTuple_Check(mro)) {
+ Py_DECREF(mro);
+ PyErr_SetString(PyExc_TypeError, "unable to get the type MRO");
+ return -1;
+ }
+
+ int check = check_immutable_bases(type->tp_name, mro, 1);
+ Py_DECREF(mro);
+ if (check < 0) {
+ return -1;
+ }
+
+ type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
+ PyType_Modified(type);
+
+ return 0;
+}
+
+
/* Cooperative 'super' */
typedef struct {