error handling fixes for argument unpacking when args/kwargs are in closures
authorStefan Behnel <scoder@users.berlios.de>
Sat, 5 Feb 2011 18:21:47 +0000 (19:21 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Sat, 5 Feb 2011 18:21:47 +0000 (19:21 +0100)
Cython/Compiler/Nodes.py
tests/run/args_unpacking_in_closure_T658.pyx [new file with mode: 0644]

index 9251e0189c5f7fd71b98a4a7f0731ca9fd4fd4a8..5895f46b3a885ca2501b4994e67b4fba874dc1fc 100644 (file)
@@ -2387,9 +2387,9 @@ class DefNode(FuncDefNode):
                 self.generate_arg_decref(self.star_arg, code)
                 if self.starstar_arg:
                     if self.starstar_arg.entry.xdecref_cleanup:
-                        code.put_var_xdecref(self.starstar_arg.entry)
+                        code.put_var_xdecref_clear(self.starstar_arg.entry)
                     else:
-                        code.put_var_decref(self.starstar_arg.entry)
+                        code.put_var_decref_clear(self.starstar_arg.entry)
             code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
             # The arguments are put into the closure one after the
             # other, so when type errors are found, all references in
@@ -2429,11 +2429,11 @@ class DefNode(FuncDefNode):
 
     def generate_arg_xdecref(self, arg, code):
         if arg:
-            code.put_var_xdecref(arg.entry)
+            code.put_var_xdecref_clear(arg.entry)
 
     def generate_arg_decref(self, arg, code):
         if arg:
-            code.put_var_decref(arg.entry)
+            code.put_var_decref_clear(arg.entry)
 
     def generate_stararg_copy_code(self, code):
         if not self.star_arg:
@@ -2641,7 +2641,7 @@ class DefNode(FuncDefNode):
             if self.starstar_arg:
                 code.putln("")
                 code.putln("if (unlikely(!%s)) {" % self.star_arg.entry.cname)
-                code.put_decref(self.starstar_arg.entry.cname, py_object_type)
+                code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
                 code.putln('return %s;' % self.error_value())
                 code.putln('}')
             else:
diff --git a/tests/run/args_unpacking_in_closure_T658.pyx b/tests/run/args_unpacking_in_closure_T658.pyx
new file mode 100644 (file)
index 0000000..c81d836
--- /dev/null
@@ -0,0 +1,14 @@
+
+def outer(int x, *args, **kwargs):
+    """
+    >>> inner = outer(1, 2, a=3)
+    >>> inner()
+    (1, (2,), {'a': 3})
+
+    >>> inner = outer('abc', 2, a=3)
+    Traceback (most recent call last):
+    TypeError: an integer is required
+    """
+    def inner():
+        return x, args, kwargs
+    return inner