Commit 2ec4d662 authored by Stefan Behnel's avatar Stefan Behnel

clean up metaclass code

parent dbf0e770
......@@ -1450,7 +1450,7 @@ class NameNode(AtomicExprNode):
return # There was an error earlier
if entry.is_builtin and Options.cache_builtins:
return # Lookup already cached
elif entry.is_real_dict:
elif entry.is_pyclass_attr:
assert entry.type.is_pyobject, "Python global or builtin not a Python object"
interned_cname = code.intern_identifier(self.entry.name)
if entry.is_builtin:
......@@ -1459,7 +1459,7 @@ class NameNode(AtomicExprNode):
namespace = entry.scope.namespace_cname
code.globalstate.use_utility_code(getitem_dict_utility_code)
code.putln(
'%s = __Pyx_PyDict_GetItem(%s, %s); %s' % (
'%s = PyObject_GetItem(%s, %s); %s' % (
self.result(),
namespace,
interned_cname,
......@@ -1521,9 +1521,9 @@ class NameNode(AtomicExprNode):
# in Py2.6+, we need to invalidate the method cache
code.putln("PyType_Modified(%s);" %
entry.scope.parent_type.typeptr_cname)
elif entry.is_real_dict:
elif entry.is_pyclass_attr:
code.put_error_if_neg(self.pos,
'PyDict_SetItem(%s, %s, %s)' % (
'PyObject_SetItem(%s, %s, %s)' % (
namespace,
interned_cname,
rhs.py_result()))
......@@ -1608,10 +1608,10 @@ class NameNode(AtomicExprNode):
if not self.entry.is_pyglobal:
error(self.pos, "Deletion of local or C global name not supported")
return
if self.entry.is_real_dict:
if self.entry.is_pyclass_attr:
namespace = self.entry.scope.namespace_cname
code.put_error_if_neg(self.pos,
'PyDict_DelItemString(%s, "%s")' % (
'PyMapping_DelItemString(%s, "%s")' % (
namespace,
self.entry.name))
else:
......@@ -4494,7 +4494,7 @@ class ClassNode(ExprNode, ModuleNameMixin):
self.keyword_args.analyse_types(env)
if self.starstar_arg:
self.starstar_arg.analyse_types(env)
if self.starstar_arg:
# make sure we have a Python object as **kwargs mapping
self.starstar_arg = \
self.starstar_arg.coerce_to_pyobject(env)
self.type = py_object_type
......@@ -4504,7 +4504,7 @@ class ClassNode(ExprNode, ModuleNameMixin):
self.set_mod_name(env)
def may_be_none(self):
return False
return True
gil_message = "Constructing Python class"
......@@ -4540,6 +4540,7 @@ class ClassNode(ExprNode, ModuleNameMixin):
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result())
class BoundMethodNode(ExprNode):
# Helper class used in the implementation of Python
# class definitions. Constructs an bound method
......@@ -7184,10 +7185,12 @@ create_class_utility_code = UtilityCode(
proto = """
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
PyObject *modname, PyObject *kwargs); /*proto*/
static int __Pyx_PrepareClass(PyObject *metaclass, PyObject *bases, PyObject *name,
PyObject *mkw, PyObject *dict); /*proto*/
""",
impl = """
static int __Pyx_PrepareClass(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *mkw, PyObject *dict)
{
static int __Pyx_PrepareClass(PyObject *metaclass, PyObject *bases, PyObject *name,
PyObject *mkw, PyObject *dict) {
PyObject *prep;
PyObject *pargs;
PyObject *ns;
......@@ -7219,9 +7222,8 @@ static int __Pyx_PrepareClass(PyObject *metaclass, PyObject *bases, PyObject *na
return 0;
}
static PyObject *__Pyx_CreateClass(
PyObject *bases, PyObject *dict, PyObject *name, PyObject *modname, PyObject *kwargs)
{
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name,
PyObject *modname, PyObject *kwargs) {
PyObject *result = NULL;
PyObject *metaclass = NULL;
PyObject *mkw = NULL;
......@@ -7232,7 +7234,7 @@ static PyObject *__Pyx_CreateClass(
/* Python3 metaclasses */
if (kwargs) {
mkw = PyDict_Copy(kwargs); /* Don't modify kwargs passed in! */
if (mkw == NULL)
if (!mkw)
return NULL;
metaclass = PyDict_GetItemString(mkw, "metaclass");
if (metaclass) {
......@@ -7243,19 +7245,16 @@ static PyObject *__Pyx_CreateClass(
goto bad;
}
}
if (!metaclass) {
/* Python2 __metaclass__ */
if (metaclass == NULL) {
metaclass = PyDict_GetItemString(dict, "__metaclass__");
if (metaclass)
Py_INCREF(metaclass);
}
if (!metaclass) {
/* Default metaclass */
if (metaclass == NULL) {
#if PY_MAJOR_VERSION < 3
if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
PyObject *base = PyTuple_GET_ITEM(bases, 0);
metaclass = PyObject_GetAttrString(base, "__class__");
if (metaclass == NULL) {
if (!metaclass) {
PyErr_Clear();
metaclass = (PyObject *)base->ob_type;
}
......@@ -7268,6 +7267,7 @@ static PyObject *__Pyx_CreateClass(
} else
metaclass = (PyObject *) &PyType_Type;
#endif
}
Py_INCREF(metaclass);
}
if (mkw && PyDict_Size(mkw) > 0) {
......@@ -7280,7 +7280,6 @@ static PyObject *__Pyx_CreateClass(
}
bad:
Py_DECREF(metaclass);
if (mkw)
Py_XDECREF(mkw);
return result;
}
......
......@@ -70,7 +70,7 @@ class Entry(object):
# or class attribute during
# class construction
# is_member boolean Is an assigned class member
# is_real_dict boolean Is a real dict, PyClass attributes dict
# is_pyclass_attr boolean Is a name in a Python class namespace
# is_variable boolean Is a variable
# is_cfunction boolean Is a C function
# is_cmethod boolean Is a C method of an extension type
......@@ -132,7 +132,7 @@ class Entry(object):
is_cglobal = 0
is_pyglobal = 0
is_member = 0
is_real_dict = 0
is_pyclass_attr = 0
is_variable = 0
is_cfunction = 0
is_cmethod = 0
......@@ -1419,7 +1419,7 @@ class PyClassScope(ClassScope):
entry = Scope.declare_var(self, name, type, pos,
cname, visibility, is_cdef)
entry.is_pyglobal = 1
entry.is_real_dict = 1
entry.is_pyclass_attr = 1
return entry
def add_default_value(self, type):
......
......@@ -12,6 +12,7 @@ class Foo(object):
"""
__metaclass__ = Base
class Py3Base(type):
def __new__(cls, name, bases, attrs, foo=None):
attrs['foo'] = foo
......
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