@@ -131,6 +131,52 @@ static bool _CPy_IsSafeMetaClass(PyTypeObject *metaclass) {
131
131
return matches ;
132
132
}
133
133
134
+ #if CPY_3_13_FEATURES
135
+
136
+ // Adapted from CPython 3.13.0b3
137
+ /* Determine the most derived metatype. */
138
+ PyObject * CPy_CalculateMetaclass (PyObject * metatype , PyObject * bases )
139
+ {
140
+ Py_ssize_t i , nbases ;
141
+ PyTypeObject * winner ;
142
+ PyObject * tmp ;
143
+ PyTypeObject * tmptype ;
144
+
145
+ /* Determine the proper metatype to deal with this,
146
+ and check for metatype conflicts while we're at it.
147
+ Note that if some other metatype wins to contract,
148
+ it's possible that its instances are not types. */
149
+
150
+ nbases = PyTuple_GET_SIZE (bases );
151
+ winner = (PyTypeObject * )metatype ;
152
+ for (i = 0 ; i < nbases ; i ++ ) {
153
+ tmp = PyTuple_GET_ITEM (bases , i );
154
+ tmptype = Py_TYPE (tmp );
155
+ if (PyType_IsSubtype (winner , tmptype ))
156
+ continue ;
157
+ if (PyType_IsSubtype (tmptype , winner )) {
158
+ winner = tmptype ;
159
+ continue ;
160
+ }
161
+ /* else: */
162
+ PyErr_SetString (PyExc_TypeError ,
163
+ "metaclass conflict: "
164
+ "the metaclass of a derived class "
165
+ "must be a (non-strict) subclass "
166
+ "of the metaclasses of all its bases" );
167
+ return NULL ;
168
+ }
169
+ return (PyObject * )winner ;
170
+ }
171
+
172
+ #else
173
+
174
+ PyObject * CPy_CalculateMetaclass (PyObject * metatype , PyObject * bases ) {
175
+ return (PyObject * )_PyType_CalculateMetaclass ((PyTypeObject * )metatype , bases );
176
+ }
177
+
178
+ #endif
179
+
134
180
// Create a heap type based on a template non-heap type.
135
181
// This is super hacky and maybe we should suck it up and use PyType_FromSpec instead.
136
182
// We allow bases to be NULL to represent just inheriting from object.
@@ -163,7 +209,7 @@ PyObject *CPyType_FromTemplate(PyObject *template,
163
209
// Find the appropriate metaclass from our base classes. We
164
210
// care about this because Generic uses a metaclass prior to
165
211
// Python 3.7.
166
- metaclass = _PyType_CalculateMetaclass ( metaclass , bases );
212
+ metaclass = ( PyTypeObject * ) CPy_CalculateMetaclass (( PyObject * ) metaclass , bases );
167
213
if (!metaclass )
168
214
goto error ;
169
215
0 commit comments