Skip to content

Commit 41fa7e9

Browse files
committed
Factor out base update in a separate helper
1 parent 5d5211d commit 41fa7e9

1 file changed

Lines changed: 62 additions & 42 deletions

File tree

Python/bltinmodule.c

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)