From: Robert Bradshaw Date: Sun, 19 Aug 2007 02:44:28 +0000 (-0700) Subject: Avoid call to PyArg_ParseTupleAndKeywords for zero- and single-argument functions. X-Git-Tag: 0.9.6.14~29^2~129^2~17^2~3 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=8c68f60416f9ac40da2948b23a8222aa059852a5;p=cython.git Avoid call to PyArg_ParseTupleAndKeywords for zero- and single-argument functions. --- diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 4cb2984f..14fbe2a4 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -294,7 +294,7 @@ class CCodeWriter: '{"%s", (PyCFunction)%s, %s, %s}%s' % ( entry.name, entry.func_cname, - entry.meth_flags, + "|".join(entry.meth_flags), doc_code, term)) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index c7329d57..4bf256b9 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -8,6 +8,7 @@ import Code from Errors import error, warning, InternalError import Naming import PyrexTypes +import TypeSlots from PyrexTypes import py_object_type, error_type, CTypedefType from Symtab import ModuleScope, LocalScope, \ StructOrUnionScope, PyClassScope, CClassScope @@ -819,6 +820,13 @@ class DefNode(FuncDefNode): def analyse_signature(self, env): any_type_tests_needed = 0 + if self.entry.signature is TypeSlots.pymethod_signature: + if len(self.args) == 1: + self.entry.signature = TypeSlots.unaryfunc + self.entry.meth_flags = [TypeSlots.method_noargs] + elif len(self.args) == 2 and self.args[1].type.is_pyobject and self.args[1].default is None: + self.entry.signature = TypeSlots.ibinaryfunc + self.entry.meth_flags = [TypeSlots.method_onearg] sig = self.entry.signature nfixed = sig.num_fixed_args() for i in range(nfixed): @@ -963,6 +971,8 @@ class DefNode(FuncDefNode): else: arg_code_list.append( arg.hdr_type.declaration_code(arg.hdr_cname)) + if self.entry.meth_flags == [TypeSlots.method_noargs]: + arg_code_list.append("PyObject *unused") if sig.has_generic_args: arg_code_list.append( "PyObject *%s, PyObject *%s" diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 1fadd21e..88e7af5b 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -303,7 +303,7 @@ class Scope: # Add an entry for a Python function. entry = self.declare_var(name, py_object_type, pos) entry.signature = pyfunction_signature - entry.meth_flags = "METH_VARARGS|METH_KEYWORDS" + entry.meth_flags = [TypeSlots.method_varargs, TypeSlots.method_keywords] self.pyfunc_entries.append(entry) return entry @@ -1091,13 +1091,13 @@ class CClassScope(ClassScope): # signature declared in advance. entry.signature = special_sig if special_sig == TypeSlots.unaryfunc: - entry.meth_flags = "METH_NOARGS|METH_COEXIST" + entry.meth_flags = [TypeSlots.method_noargs, TypeSlots.method_coexist] elif special_sig == TypeSlots.binaryfunc or special_sig == TypeSlots.ibinaryfunc: - entry.meth_flags = "METH_O|METH_COEXIST" + entry.meth_flags = [TypeSlots.method_onearg, TypeSlots.method_coexist] else: entry.meth_flags = None # should it generate a wrapper function? else: - entry.meth_flags = "METH_VARARGS|METH_KEYWORDS" + entry.meth_flags = [TypeSlots.method_varargs, TypeSlots.method_keywords] entry.signature = pymethod_signature self.pyfunc_entries.append(entry) diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py index 530daa2c..fffd8d9e 100644 --- a/Cython/Compiler/TypeSlots.py +++ b/Cython/Compiler/TypeSlots.py @@ -590,3 +590,12 @@ MethodSlot(delattrofunc, "", "__delattr__") MethodSlot(descrgetfunc, "", "__get__") MethodSlot(descrsetfunc, "", "__set__") MethodSlot(descrdelfunc, "", "__delete__") + + +# Method flags for python-exposed methods. + +method_noargs = "METH_NOARGS" +method_onearg = "METH_O" +method_varargs = "METH_VARARGS" +method_keywords = "METH_KEYWORDS" +method_coexist = "METH_COEXIST"