@@ -48,6 +48,9 @@ _Py_IDENTIFIER(__new__);
4848static PyObject *
4949_PyType_LookupId (PyTypeObject * type , struct _Py_Identifier * name );
5050
51+ static PyObject *
52+ slot_tp_new (PyTypeObject * type , PyObject * args , PyObject * kwds );
53+
5154unsigned int
5255PyType_ClearCache (void )
5356{
@@ -2375,22 +2378,75 @@ static short slotoffsets[] = {
23752378};
23762379
23772380PyObject *
2378- PyType_FromSpec (PyType_Spec * spec )
2381+ PyType_FromSpecWithBases (PyType_Spec * spec , PyObject * bases )
23792382{
23802383 PyHeapTypeObject * res = (PyHeapTypeObject * )PyType_GenericAlloc (& PyType_Type , 0 );
2384+ PyTypeObject * type , * base ;
2385+ char * s ;
23812386 char * res_start = (char * )res ;
23822387 PyType_Slot * slot ;
2388+
2389+ /* Set the type name and qualname */
2390+ s = strrchr (spec -> name , '.' );
2391+ if (s == NULL )
2392+ s = (char * )spec -> name ;
2393+ else
2394+ s ++ ;
23832395
23842396 if (res == NULL )
23852397 return NULL ;
2386- res -> ht_name = PyUnicode_FromString (spec -> name );
2398+ res -> ht_name = PyUnicode_FromString (s );
23872399 if (!res -> ht_name )
23882400 goto fail ;
23892401 res -> ht_qualname = res -> ht_name ;
23902402 Py_INCREF (res -> ht_qualname );
2391- res -> ht_type .tp_name = _PyUnicode_AsString ( res -> ht_name ) ;
2403+ res -> ht_type .tp_name = spec -> name ;
23922404 if (!res -> ht_type .tp_name )
23932405 goto fail ;
2406+
2407+ /* Adjust for empty tuple bases */
2408+ if (!bases ) {
2409+ base = & PyBaseObject_Type ;
2410+ /* See whether Py_tp_base(s) was specified */
2411+ for (slot = spec -> slots ; slot -> slot ; slot ++ ) {
2412+ if (slot -> slot == Py_tp_base )
2413+ base = slot -> pfunc ;
2414+ else if (slot -> slot == Py_tp_bases ) {
2415+ bases = slot -> pfunc ;
2416+ Py_INCREF (bases );
2417+ }
2418+ }
2419+ if (!bases )
2420+ bases = PyTuple_Pack (1 , base );
2421+ if (!bases )
2422+ goto fail ;
2423+ }
2424+ else
2425+ Py_INCREF (bases );
2426+
2427+ /* Calculate best base, and check that all bases are type objects */
2428+ base = best_base (bases );
2429+ if (base == NULL ) {
2430+ goto fail ;
2431+ }
2432+ if (!PyType_HasFeature (base , Py_TPFLAGS_BASETYPE )) {
2433+ PyErr_Format (PyExc_TypeError ,
2434+ "type '%.100s' is not an acceptable base type" ,
2435+ base -> tp_name );
2436+ goto fail ;
2437+ }
2438+
2439+ type = (PyTypeObject * )res ;
2440+ /* Initialize essential fields */
2441+ type -> tp_as_number = & res -> as_number ;
2442+ type -> tp_as_sequence = & res -> as_sequence ;
2443+ type -> tp_as_mapping = & res -> as_mapping ;
2444+ type -> tp_as_buffer = & res -> as_buffer ;
2445+ /* Set tp_base and tp_bases */
2446+ type -> tp_bases = bases ;
2447+ bases = NULL ;
2448+ Py_INCREF (base );
2449+ type -> tp_base = base ;
23942450
23952451 res -> ht_type .tp_basicsize = spec -> basicsize ;
23962452 res -> ht_type .tp_itemsize = spec -> itemsize ;
@@ -2401,6 +2457,9 @@ PyType_FromSpec(PyType_Spec *spec)
24012457 PyErr_SetString (PyExc_RuntimeError , "invalid slot offset" );
24022458 goto fail ;
24032459 }
2460+ if (slot -> slot == Py_tp_base || slot -> slot == Py_tp_bases )
2461+ /* Processed above */
2462+ continue ;
24042463 * (void * * )(res_start + slotoffsets [slot -> slot ]) = slot -> pfunc ;
24052464
24062465 /* need to make a copy of the docstring slot, which usually
@@ -2427,13 +2486,26 @@ PyType_FromSpec(PyType_Spec *spec)
24272486 if (PyType_Ready (& res -> ht_type ) < 0 )
24282487 goto fail ;
24292488
2489+ /* Set type.__module__ */
2490+ s = strrchr (spec -> name , '.' );
2491+ if (s != NULL )
2492+ _PyDict_SetItemId (type -> tp_dict , & PyId___module__ ,
2493+ PyUnicode_FromStringAndSize (
2494+ spec -> name , (Py_ssize_t )(s - spec -> name )));
2495+
24302496 return (PyObject * )res ;
24312497
24322498 fail :
24332499 Py_DECREF (res );
24342500 return NULL ;
24352501}
24362502
2503+ PyObject *
2504+ PyType_FromSpec (PyType_Spec * spec )
2505+ {
2506+ return PyType_FromSpecWithBases (spec , NULL );
2507+ }
2508+
24372509
24382510/* Internal API to look for a name through the MRO.
24392511 This returns a borrowed reference, and doesn't set an exception! */
@@ -4763,7 +4835,7 @@ tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds)
47634835 object.__new__(dict). To do this, we check that the
47644836 most derived base that's not a heap type is this type. */
47654837 staticbase = subtype ;
4766- while (staticbase && (staticbase -> tp_flags & Py_TPFLAGS_HEAPTYPE ))
4838+ while (staticbase && (staticbase -> tp_new == slot_tp_new ))
47674839 staticbase = staticbase -> tp_base ;
47684840 /* If staticbase is NULL now, it is a really weird type.
47694841 In the spirit of backwards compatibility (?), just shut up. */
0 commit comments