raise NameError instead of KeyError when del-ing a non-existing name inside of a...
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 9 Mar 2013 08:43:00 +0000 (09:43 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 9 Mar 2013 08:43:00 +0000 (09:43 +0100)
Cython/Compiler/ExprNodes.py
tests/run/py_classbody.py

index 924918e..f5c8beb 100755 (executable)
@@ -1945,13 +1945,20 @@ class NameNode(AtomicExprNode):
         elif self.entry.is_pyclass_attr:
             namespace = self.entry.scope.namespace_cname
             interned_cname = code.intern_identifier(self.entry.name)
-            del_code = 'PyObject_DelItem(%s, %s)' % (namespace, interned_cname)
             if ignore_nonexisting:
-                code.putln('if (unlikely(%s < 0)) { if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) PyErr_Clear(); else %s }' % (
-                    del_code,
-                    code.error_goto(self.pos)))
+                key_error_code = 'PyErr_Clear(); else'
             else:
-                code.put_error_if_neg(self.pos, del_code)
+                # minor hack: fake a NameError on KeyError
+                key_error_code = (
+                    '{ PyErr_Clear(); PyErr_Format(PyExc_NameError, "name \'%%s\' is not defined", "%s"); }' %
+                    self.entry.name)
+            code.putln(
+                'if (unlikely(PyObject_DelItem(%s, %s) < 0)) {'
+                ' if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) %s'
+                ' %s '
+                '}' % (namespace, interned_cname,
+                       key_error_code,
+                       code.error_goto(self.pos)))
         elif self.entry.is_pyglobal:
             code.globalstate.use_utility_code(
                 UtilityCode.load_cached("PyObjectSetAttrStr", "ObjectHandling.c"))
index cd8e950..55f3c12 100644 (file)
@@ -57,3 +57,21 @@ class ForLoopInPyClass(object):
 
     for m in range(2):
         pass
+
+
+def del_in_class(x):
+    """
+    >>> del_in_class(True)
+    no error
+    >>> del_in_class(False)
+    NameError
+    """
+    try:
+        class Test(object):
+            if x:
+                attr = 1
+            del attr
+    except NameError:
+        print("NameError")
+    else:
+        print("no error")