clean up metaclass code
authorStefan Behnel <scoder@users.berlios.de>
Mon, 8 Nov 2010 14:33:43 +0000 (15:33 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Mon, 8 Nov 2010 14:33:43 +0000 (15:33 +0100)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Symtab.py
tests/run/metaclass.pyx

index 33458e6d503dde7cbb3a44a14f9101fa163db0fa..92963ffd50f0e7a0561c2ab3e942f8efd86cefd0 100755 (executable)
@@ -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;
 }
 """)
index c6062ec15b7cc841cf250d94ef8d4b6069b71b98..fa20a39cd81b569239b5aba38d62c9ca7577a7d9 100644 (file)
@@ -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):
index ebf2c065780886a2b1e1055dcccfb5e953169b92..f4e3175a1d474958efbb8be6a91da1332357ae06 100644 (file)
@@ -12,6 +12,7 @@ class Foo(object):
     """
     __metaclass__ = Base
 
+
 class Py3Base(type):
     def __new__(cls, name, bases, attrs, foo=None):
         attrs['foo'] = foo