@@ -131,6 +131,52 @@ static bool _CPy_IsSafeMetaClass(PyTypeObject *metaclass) {
131131 return matches ;
132132}
133133
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+
134180// Create a heap type based on a template non-heap type.
135181// This is super hacky and maybe we should suck it up and use PyType_FromSpec instead.
136182// We allow bases to be NULL to represent just inheriting from object.
@@ -163,7 +209,7 @@ PyObject *CPyType_FromTemplate(PyObject *template,
163209 // Find the appropriate metaclass from our base classes. We
164210 // care about this because Generic uses a metaclass prior to
165211 // Python 3.7.
166- metaclass = _PyType_CalculateMetaclass ( metaclass , bases );
212+ metaclass = ( PyTypeObject * ) CPy_CalculateMetaclass (( PyObject * ) metaclass , bases );
167213 if (!metaclass )
168214 goto error ;
169215
0 commit comments