Skip to content

Commit 26afdc6

Browse files
committed
POC implementation of __base_subclass__
1 parent e184cfd commit 26afdc6

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

Python/bltinmodule.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
5353
{
5454
PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns;
5555
PyObject *cls = NULL, *cell = NULL;
56+
PyObject *base_types;
5657
int isclass = 0; /* initialize to prevent gcc warning */
58+
int i, modified_bases = 0;
5759

5860
if (nargs < 2) {
5961
PyErr_SetString(PyExc_TypeError,
@@ -76,6 +78,30 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
7678
if (bases == NULL)
7779
return NULL;
7880

81+
for (i = 2; i < nargs; i++){
82+
PyObject *base, *new_base;
83+
base = args[i];
84+
if PyType_Check(base){
85+
continue;
86+
}
87+
new_base = PyObject_GetAttrString(base, "__base_subclass__");
88+
if (new_base == NULL) {
89+
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
90+
PyErr_Clear();
91+
}
92+
else {
93+
Py_DECREF(bases);
94+
return NULL;
95+
}
96+
}
97+
else {
98+
Py_INCREF(new_base);
99+
PyTuple_SET_ITEM(bases, i - 2, new_base);
100+
Py_DECREF(base);
101+
modified_bases = 1;
102+
}
103+
}
104+
79105
if (kwnames == NULL) {
80106
meta = NULL;
81107
mkw = NULL;
@@ -168,6 +194,10 @@ builtin___build_class__(PyObject *self, PyObject **args, Py_ssize_t nargs,
168194
NULL, 0, NULL, 0, NULL, 0, NULL,
169195
PyFunction_GET_CLOSURE(func));
170196
if (cell != NULL) {
197+
if (modified_bases){
198+
base_types = _PyStack_AsTupleSlice(args, nargs, 2, nargs);
199+
PyMapping_SetItemString(ns, "__orig_bases__", base_types);
200+
}
171201
PyObject *margs[3] = {name, bases, ns};
172202
cls = _PyObject_FastCallDict(meta, margs, 3, mkw);
173203
if (cls != NULL && PyType_Check(cls) && PyCell_Check(cell)) {

0 commit comments

Comments
 (0)