Commit 77eb0f6f authored by Stefan Behnel's avatar Stefan Behnel

support non-types as Py2 metaclasses

parent 455e0357
......@@ -868,35 +868,24 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
PyObject *dict, PyObject *mkw,
int calculate_metaclass, int allow_py2_metaclass) {
PyObject *result, *margs;
PyObject *py2_metaclass = NULL;
PyObject *owned_metaclass = NULL;
if (allow_py2_metaclass) {
/* honour Python2 __metaclass__ for backward compatibility */
py2_metaclass = PyObject_GetItem(dict, PYIDENT("__metaclass__"));
if (py2_metaclass) {
if (likely(PyType_Check(py2_metaclass))) {
metaclass = py2_metaclass;
calculate_metaclass = 1;
} else {
/* py2_metaclass != NULL => calculate_metaclass != 0 */
Py_DECREF(py2_metaclass);
py2_metaclass = NULL;
}
owned_metaclass = PyObject_GetItem(dict, PYIDENT("__metaclass__"));
if (owned_metaclass) {
metaclass = owned_metaclass;
} else if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) {
PyErr_Clear();
} else {
return NULL;
}
}
if (calculate_metaclass) {
if (py2_metaclass || PyType_Check(metaclass)) {
metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases);
Py_XDECREF(py2_metaclass);
if (unlikely(!metaclass))
return NULL;
} else {
Py_XDECREF(py2_metaclass);
calculate_metaclass = 0;
}
if (calculate_metaclass && (!metaclass || PyType_Check(metaclass))) {
metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases);
Py_XDECREF(owned_metaclass);
if (unlikely(!metaclass))
return NULL;
owned_metaclass = metaclass;
}
margs = PyTuple_Pack(3, name, bases, dict);
if (unlikely(!margs)) {
......@@ -905,9 +894,7 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
result = PyObject_Call(metaclass, margs, mkw);
Py_DECREF(margs);
}
if (calculate_metaclass) {
Py_DECREF(metaclass);
}
Py_XDECREF(owned_metaclass);
return result;
}
......
......@@ -15,6 +15,26 @@ class Foo(object):
"""
__metaclass__ = Base
def non_type_metaclass(name, bases, namespace):
namespace['BASES'] = [b.__name__ for b in bases]
namespace['NAME'] = name
return type(name, bases, namespace)
class FunctionAsPy2Metaclass(object):
"""
>>> obj = FunctionAsPy2Metaclass()
>>> obj.NAME
'FunctionAsPy2Metaclass'
>>> obj.BASES
['object']
>>> obj.x
1
"""
__metaclass__ = non_type_metaclass
x = 1
class ODict(dict):
def __init__(self):
dict.__init__(self)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment