second try to fix ticket #583: method signatures of overridden C methods in pure...
authorStefan Behnel <scoder@users.berlios.de>
Mon, 8 Nov 2010 11:34:32 +0000 (12:34 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Mon, 8 Nov 2010 11:34:32 +0000 (12:34 +0100)
Cython/Compiler/Nodes.py
Cython/Compiler/ParseTreeTransforms.py
tests/run/pure_mode_cmethod_inheritance_T583.pxd
tests/run/pure_mode_cmethod_inheritance_T583.py

index 83e89d4ab5737bca07967bbe387a58c166efa72c..0735e39d10c2ad71b4a43c538854b74445d7580d 100644 (file)
@@ -534,8 +534,9 @@ class CFuncDeclaratorNode(CDeclaratorNode):
         if nonempty:
             nonempty -= 1
         func_type_args = []
-        for arg_node in self.args:
-            name_declarator, type = arg_node.analyse(env, nonempty = nonempty)
+        for i, arg_node in enumerate(self.args):
+            name_declarator, type = arg_node.analyse(env, nonempty = nonempty,
+                                                     is_self_arg = (i == 0 and env.is_c_class_scope))
             name = name_declarator.name
             if name_declarator.cname:
                 error(self.pos, 
@@ -649,8 +650,9 @@ class CArgDeclNode(Node):
     default_value = None
     annotation = None
 
-    def analyse(self, env, nonempty = 0):
-        #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
+    def analyse(self, env, nonempty = 0, is_self_arg = False):
+        if is_self_arg:
+            self.base_type.is_self_arg = self.is_self_arg = True
         if self.type is None:
             # The parser may missinterpret names as types...
             # We fix that here.
@@ -1600,7 +1602,7 @@ class CFuncDefNode(FuncDefNode):
     def analyse_declarations(self, env):
         self.directive_locals.update(env.directives['locals'])
         base_type = self.base_type.analyse(env)
-        # The 2 here is because we need both function and argument names. 
+        # The 2 here is because we need both function and argument names.
         name_declarator, type = self.declarator.analyse(base_type, env, nonempty = 2 * (self.body is not None))
         if not type.is_cfunction:
             error(self.pos, 
@@ -1907,12 +1909,15 @@ class DefNode(FuncDefNode):
                                               is_overridable = True)
             cfunc = CVarDefNode(self.pos, type=cfunc_type)
         else:
+            if scope is None:
+                scope = cfunc.scope
             cfunc_type = cfunc.type
             if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
                 error(self.pos, "wrong number of arguments")
                 error(cfunc.pos, "previous declaration here")
-            for formal_arg, type_arg in zip(self.args, cfunc_type.args):
-                name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
+            for i, (formal_arg, type_arg) in enumerate(zip(self.args, cfunc_type.args)):
+                name_declarator, type = formal_arg.analyse(scope, nonempty=1,
+                                                           is_self_arg = (i == 0 and scope.is_c_class_scope))
                 if type is None or type is PyrexTypes.py_object_type:
                     formal_arg.type = type_arg.type
                     formal_arg.name_declarator = name_declarator
index 753dfb4244d4c27d4a7ebaedfcf792ff8fa7e219..2be6f7a42164cb1448e7e1ad164508bb69d8434a 100644 (file)
@@ -1233,15 +1233,11 @@ class AlignFunctionDefinitions(CythonTransform):
     def visit_DefNode(self, node):
         pxd_def = self.scope.lookup(node.name)
         if pxd_def:
-            if self.scope.is_c_class_scope and len(pxd_def.type.args) > 0:
-                # The self parameter type needs adjusting.
-                pxd_def.type.args[0].type = self.scope.parent_type
-            if pxd_def.is_cfunction:
-                node = node.as_cfunction(pxd_def)
-            else:
+            if not pxd_def.is_cfunction:
                 error(node.pos, "'%s' redeclared" % node.name)
                 error(pxd_def.pos, "previous declaration here")
                 return None
+            node = node.as_cfunction(pxd_def)
         elif self.scope.is_module_scope and self.directives['auto_cpdef']:
             node = node.as_cfunction(scope=self.scope)
         # Enable this when internal def functions are allowed. 
index 79d4af9e578dbb8482da8ee4c3eea0181df5a5fe..f6108008908f1bdc367157d3bc5a0b02592519d9 100644 (file)
@@ -1,5 +1,19 @@
 cdef class Base:
-    cpdef str method(self)
+    cpdef str noargs(self)
+    cpdef str int_arg(self, int i)
+    cpdef str _class(tp)
 
 cdef class Derived(Base):
-    cpdef str method(self)
+    cpdef str noargs(self)
+    cpdef str int_arg(self, int i)
+    cpdef str _class(tp)
+
+cdef class DerivedDerived(Derived):
+    cpdef str noargs(self)
+    cpdef str int_arg(self, int i)
+    cpdef str _class(tp)
+
+cdef class Derived2(Base):
+    cpdef str noargs(self)
+    cpdef str int_arg(self, int i)
+    cpdef str _class(tp)
index 44a88f197ff50f540dd2b498893e833b0d75b7e4..92a284730a49a7dcec48368e4d17a5e9461ac97f 100644 (file)
@@ -1,18 +1,74 @@
 class Base(object):
     '''
     >>> base = Base()
-    >>> print(base.method())
+    >>> print(base.noargs())
+    Base
+    >>> print(base.int_arg(1))
+    Base
+    >>> print(base._class())
     Base
     '''
-    def method(self):
+    def noargs(self):
+        return "Base"
+    def int_arg(self, i):
+        return "Base"
+    @classmethod
+    def _class(tp):
         return "Base"
 
 
 class Derived(Base):
     '''
     >>> derived = Derived()
-    >>> print(derived.method())
+    >>> print(derived.noargs())
+    Derived
+    >>> print(derived.int_arg(1))
+    Derived
+    >>> print(derived._class())
     Derived
     '''
-    def method(self):
+    def noargs(self):
+        return "Derived"
+    def int_arg(self, i):
+        return "Derived"
+    @classmethod
+    def _class(tp):
         return "Derived"
+
+
+class DerivedDerived(Derived):
+    '''
+    >>> derived = DerivedDerived()
+    >>> print(derived.noargs())
+    DerivedDerived
+    >>> print(derived.int_arg(1))
+    DerivedDerived
+    >>> print(derived._class())
+    DerivedDerived
+    '''
+    def noargs(self):
+        return "DerivedDerived"
+    def int_arg(self, i):
+        return "DerivedDerived"
+    @classmethod
+    def _class(tp):
+        return "DerivedDerived"
+
+
+class Derived2(Base):
+    '''
+    >>> derived = Derived2()
+    >>> print(derived.noargs())
+    Derived2
+    >>> print(derived.int_arg(1))
+    Derived2
+    >>> print(derived._class())
+    Derived2
+    '''
+    def noargs(self):
+        return "Derived2"
+    def int_arg(self, i):
+        return "Derived2"
+    @classmethod
+    def _class(tp):
+        return "Derived2"