@@ -46,39 +46,15 @@ _Py_IDENTIFIER(stderr);
4646
4747#include "clinic/bltinmodule.c.h"
4848
49- /* AC: cannot convert yet, waiting for *args support */
50- static PyObject *
51- builtin___build_class__ (PyObject * self , PyObject * * args , Py_ssize_t nargs ,
52- PyObject * kwnames )
49+ static PyObject *
50+ update_bases (PyObject * bases , PyObject * * args , int nargs , int * modified_bases )
5351{
54- PyObject * func , * name , * bases , * mkw , * meta , * winner , * prep , * ns , * new_bases ;
55- PyObject * cls = NULL , * cell = NULL ;
56- PyObject * base_types ;
57- int isclass = 0 ; /* initialize to prevent gcc warning */
58- int i , modified_bases = 0 ;
59-
60- if (nargs < 2 ) {
61- PyErr_SetString (PyExc_TypeError ,
62- "__build_class__: not enough arguments" );
63- return NULL ;
64- }
65- func = args [0 ]; /* Better be callable */
66- if (!PyFunction_Check (func )) {
67- PyErr_SetString (PyExc_TypeError ,
68- "__build_class__: func must be a function" );
69- return NULL ;
70- }
71- name = args [1 ];
72- if (!PyUnicode_Check (name )) {
73- PyErr_SetString (PyExc_TypeError ,
74- "__build_class__: name is not a string" );
75- return NULL ;
76- }
77-
78- bases = _PyStack_AsTupleSlice (args , nargs , 2 , nargs );
79- if (bases == NULL )
80- return NULL ;
52+ int i , ind , tot_nones ;
53+ PyObject * new_bases ;
54+ assert (PyTuple_Check (bases ));
8155
56+ /* We have a separate cycle to calculate replacements with the idea that
57+ most cases we just scroll quickly though it and return original bases */
8258 for (i = 2 ; i < nargs ; i ++ ){
8359 PyObject * base , * new_base , * new_base_meth ;
8460 PyObject * stack [1 ];
@@ -92,7 +68,6 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
9268 PyErr_Clear ();
9369 }
9470 else {
95- Py_DECREF (bases );
9671 return NULL ;
9772 }
9873 }
@@ -101,32 +76,31 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
10176 PyErr_Format (PyExc_TypeError ,
10277 "attribute of type '%.200s' is not callable" ,
10378 Py_TYPE (new_base_meth )-> tp_name );
104- Py_DECREF (bases );
10579 return NULL ;
10680 }
10781 stack [0 ] = bases ;
10882 new_base = _PyObject_FastCall (new_base_meth , stack , 1 );
10983 if (new_base == NULL ){
110- Py_DECREF (bases );
11184 return NULL ;
11285 }
11386 Py_INCREF (new_base );
11487 args [i ] = new_base ;
115- modified_bases = 1 ;
88+ * modified_bases = 1 ;
11689 }
11790 }
11891
119- if (modified_bases ){
120- int ind , tot_nones = 0 ;
92+ if (* modified_bases ){
93+ /* Find out have many bases wants to be removed to pre-allocate
94+ the tuple for new bases */
95+ tot_nones = 0 ;
12196 for (i = 2 ; i < nargs ; i ++ ){
12297 if (args [i ] == Py_None ){
12398 tot_nones ++ ;
12499 }
125100 }
126-
127- ind = 0 ;
128- /* Remove all None's from base classes */
129101 new_bases = PyTuple_New (nargs - 2 - tot_nones );
102+ /* Remove all None's from base classes */
103+ ind = 0 ;
130104 for (i = 2 ; i < nargs ; i ++ ){
131105 PyObject * base ;
132106 base = args [i ];
@@ -136,7 +110,54 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
136110 ind ++ ;
137111 }
138112 }
113+ return new_bases ;
114+ }
115+ else {
116+ return bases ;
117+ }
118+ }
119+
120+
121+ /* AC: cannot convert yet, waiting for *args support */
122+ static PyObject *
123+ builtin___build_class__ (PyObject * self , PyObject * * args , Py_ssize_t nargs ,
124+ PyObject * kwnames )
125+ {
126+ PyObject * func , * name , * bases , * mkw , * meta , * winner , * prep , * ns ;
127+ PyObject * new_bases , * old_bases = NULL ;
128+ PyObject * cls = NULL , * cell = NULL ;
129+ int isclass = 0 ; /* initialize to prevent gcc warning */
130+ int modified_bases = 0 ;
131+
132+ if (nargs < 2 ) {
133+ PyErr_SetString (PyExc_TypeError ,
134+ "__build_class__: not enough arguments" );
135+ return NULL ;
136+ }
137+ func = args [0 ]; /* Better be callable */
138+ if (!PyFunction_Check (func )) {
139+ PyErr_SetString (PyExc_TypeError ,
140+ "__build_class__: func must be a function" );
141+ return NULL ;
142+ }
143+ name = args [1 ];
144+ if (!PyUnicode_Check (name )) {
145+ PyErr_SetString (PyExc_TypeError ,
146+ "__build_class__: name is not a string" );
147+ return NULL ;
148+ }
149+
150+ bases = _PyStack_AsTupleSlice (args , nargs , 2 , nargs );
151+ if (bases == NULL )
152+ return NULL ;
153+
154+ new_bases = update_bases (bases , args , nargs , & modified_bases );
155+ if (new_bases == NULL ){
139156 Py_DECREF (bases );
157+ return NULL ;
158+ }
159+ else {
160+ old_bases = bases ;
140161 bases = new_bases ;
141162 }
142163
@@ -233,8 +254,7 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
233254 PyFunction_GET_CLOSURE (func ));
234255 if (cell != NULL ) {
235256 if (modified_bases ){
236- base_types = _PyStack_AsTupleSlice (args , nargs , 2 , nargs );
237- PyMapping_SetItemString (ns , "__orig_bases__" , base_types );
257+ PyMapping_SetItemString (ns , "__orig_bases__" , old_bases );
238258 }
239259 PyObject * margs [3 ] = {name , bases , ns };
240260 cls = _PyObject_FastCallDict (meta , margs , 3 , mkw );
0 commit comments