From 191b92312782dfa8fe6f5e45bba5eb59663e8f25 Mon Sep 17 00:00:00 2001 From: Robert Bradshaw <robertwb@gmail.com> Date: Sun, 13 Jul 2014 02:25:11 -0700 Subject: [PATCH] Fix infinite recurison when using super with cpdef methods. This should also be a (small) performance improvement. --- CHANGES.rst | 2 ++ Cython/Compiler/Nodes.py | 13 +++++++++++++ tests/run/py3k_super.pyx | 24 ++++++++++++++++++++---- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 06949f5f2..ef9f3c969 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -84,6 +84,8 @@ Bugs fixed * Correctly handle ``from cython.submodule cimport name``. +* Fix infinite recursion when using super with cpdef methods. + Other changes ------------- diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 0e8851417..33f7df772 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -2286,6 +2286,7 @@ class CFuncDefNode(FuncDefNode): "private types") def call_self_node(self, omit_optional_args=0, is_module_scope=0): + # OLD - DELETE from . import ExprNodes args = self.type.args if omit_optional_args: @@ -2300,6 +2301,18 @@ class CFuncDefNode(FuncDefNode): c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1-is_module_scope:]], wrapper_call=skip_dispatch) return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call) + def call_self_node(self, omit_optional_args=0, is_module_scope=0): + from . import ExprNodes + args = self.type.args + if omit_optional_args: + args = args[:len(args) - self.type.optional_arg_count] + arg_names = [arg.name for arg in args] + cfunc = ExprNodes.PythonCapiFunctionNode(self.pos, self.entry.name, self.entry.func_cname, self.type) + cfunc.entry = self.entry + skip_dispatch = not is_module_scope or Options.lookup_module_cpdef + c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names], wrapper_call=skip_dispatch) + return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call) + def declare_arguments(self, env): for arg in self.type.args: if not arg.name: diff --git a/tests/run/py3k_super.pyx b/tests/run/py3k_super.pyx index 0fd20f130..97ff3de14 100644 --- a/tests/run/py3k_super.pyx +++ b/tests/run/py3k_super.pyx @@ -63,13 +63,29 @@ def test_class_cell_empty(): cdef class CClassBase(object): def method(self): - return 1 + return 'def' + +# cpdef method_cp(self): +# return 'cpdef' +# cdef method_c(self): +# return 'cdef' +# def call_method_c(self): +# return self.method_c() -cdef class CClassSuper(CClassBase): +cdef class CClassSub(CClassBase): """ - >>> CClassSuper().method() - 1 + >>> CClassSub().method() + 'def' """ +# >>> CClassSub().method_cp() +# 'cpdef' +# >>> CClassSub().call_method_c() +# 'cdef' def method(self): return super().method() + +# cpdef method_cp(self): +# return super().method_cp() +# cdef method_c(self): +# return super().method_c() -- 2.30.9