From: Stefan Behnel Date: Mon, 8 Nov 2010 14:33:43 +0000 (+0100) Subject: clean up metaclass code X-Git-Tag: 0.14.alpha0~201 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=2ec4d662dc4af74bbc4db41178c79ffa1557a1c4;p=cython.git clean up metaclass code --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 33458e6d..92963ffd 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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 @@ -7183,11 +7184,13 @@ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { create_class_utility_code = UtilityCode( proto = """ static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, - PyObject *modname, PyObject *kwargs); /*proto*/ + 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,31 +7245,29 @@ static PyObject *__Pyx_CreateClass( goto bad; } } - /* Python2 __metaclass__ */ - if (metaclass == NULL) { + if (!metaclass) { + /* Python2 __metaclass__ */ metaclass = PyDict_GetItemString(dict, "__metaclass__"); - if (metaclass) - Py_INCREF(metaclass); - } - /* Default metaclass */ - if (metaclass == NULL) { + if (!metaclass) { + /* Default metaclass */ #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) { - PyErr_Clear(); - metaclass = (PyObject *)base->ob_type; - } - } else - metaclass = (PyObject *) &PyClass_Type; + if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) { + PyObject *base = PyTuple_GET_ITEM(bases, 0); + metaclass = PyObject_GetAttrString(base, "__class__"); + if (!metaclass) { + PyErr_Clear(); + metaclass = (PyObject *)base->ob_type; + } + } else + metaclass = (PyObject *) &PyClass_Type; #else - if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) { - PyObject *base = PyTuple_GET_ITEM(bases, 0); - metaclass = (PyObject *)base->ob_type; - } else - metaclass = (PyObject *) &PyType_Type; + if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) { + PyObject *base = PyTuple_GET_ITEM(bases, 0); + metaclass = (PyObject *)base->ob_type; + } else + metaclass = (PyObject *) &PyType_Type; #endif + } Py_INCREF(metaclass); } if (mkw && PyDict_Size(mkw) > 0) { @@ -7280,8 +7280,7 @@ static PyObject *__Pyx_CreateClass( } bad: Py_DECREF(metaclass); - if (mkw) - Py_XDECREF(mkw); + Py_XDECREF(mkw); return result; } """) diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index c6062ec1..fa20a39c 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -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): diff --git a/tests/run/metaclass.pyx b/tests/run/metaclass.pyx index ebf2c065..f4e3175a 100644 --- a/tests/run/metaclass.pyx +++ b/tests/run/metaclass.pyx @@ -12,6 +12,7 @@ class Foo(object): """ __metaclass__ = Base + class Py3Base(type): def __new__(cls, name, bases, attrs, foo=None): attrs['foo'] = foo