fix T477 by refactor FuncDefNode, so cython decorators can applied to cdef function
authorHaoyu Bai <baihaoyu@gmail.com>
Wed, 30 Mar 2011 20:19:14 +0000 (04:19 +0800)
committerHaoyu Bai <baihaoyu@gmail.com>
Wed, 30 Mar 2011 20:19:31 +0000 (04:19 +0800)
Cython/Compiler/Nodes.py
tests/run/cdef_locals_decorator_T477.pyx [new file with mode: 0644]

index 609489f1758a09bde72f7a7476c64ed54c8d809f..476a89224d349a289462e2f58316b98b71d78cd1 100644 (file)
@@ -1191,6 +1191,22 @@ class FuncDefNode(StatNode, BlockNode):
             elif default_seen:
                 error(arg.pos, "Non-default argument following default argument")
 
+    def align_argument_type(self, env, arg):
+        directive_locals = self.directive_locals
+        type = arg.type
+        if arg.name in directive_locals:
+            type_node = directive_locals[arg.name]
+            other_type = type_node.analyse_as_type(env)
+            if other_type is None:
+                error(type_node.pos, "Not a type")
+            elif (type is not PyrexTypes.py_object_type 
+                    and not type.same_as(other_type)):
+                error(arg.base_type.pos, "Signature does not agree with previous declaration")
+                error(type_node.pos, "Previous declaration here")
+            else:
+                arg.type = other_type
+        return arg
+
     def need_gil_acquisition(self, lenv):
         return 0
 
@@ -1646,6 +1662,7 @@ class CFuncDefNode(FuncDefNode):
             declarator = declarator.base
         self.args = declarator.args
         for formal_arg, type_arg in zip(self.args, type.args):
+            self.align_argument_type(env, type_arg)
             formal_arg.type = type_arg.type
             formal_arg.name = type_arg.name
             formal_arg.cname = type_arg.cname
@@ -2017,28 +2034,18 @@ class DefNode(FuncDefNode):
         allow_none_for_extension_args = env.directives['allow_none_for_extension_args']
         for arg in self.args:
             if hasattr(arg, 'name'):
-                type = arg.type
                 name_declarator = None
             else:
                 base_type = arg.base_type.analyse(env)
                 name_declarator, type = \
                     arg.declarator.analyse(base_type, env)
                 arg.name = name_declarator.name
-            if arg.name in directive_locals:
-                type_node = directive_locals[arg.name]
-                other_type = type_node.analyse_as_type(env)
-                if other_type is None:
-                    error(type_node.pos, "Not a type")
-                elif (type is not PyrexTypes.py_object_type
-                        and not type.same_as(other_type)):
-                    error(arg.base_type.pos, "Signature does not agree with previous declaration")
-                    error(type_node.pos, "Previous declaration here")
-                else:
-                    type = other_type
+                arg.type = type
+            self.align_argument_type(env, arg)
             if name_declarator and name_declarator.cname:
                 error(self.pos,
                     "Python function argument cannot have C name specification")
-            arg.type = type.as_argument_type()
+            arg.type = arg.type.as_argument_type()
             arg.hdr_type = None
             arg.needs_conversion = 0
             arg.needs_type_test = 0
diff --git a/tests/run/cdef_locals_decorator_T477.pyx b/tests/run/cdef_locals_decorator_T477.pyx
new file mode 100644 (file)
index 0000000..35aae28
--- /dev/null
@@ -0,0 +1,11 @@
+import cython
+@cython.locals(x=double)
+cdef func(x):
+    return x**2
+
+def test():
+    """
+    >>> isinstance(test(), float)
+    True
+    """
+    return func(2)