compiler directive to control METH_O and METH_NOARGS flags (ticket #295)
authorLisandro Dalcin <dalcinl@gmail.com>
Tue, 28 Apr 2009 13:25:43 +0000 (10:25 -0300)
committerLisandro Dalcin <dalcinl@gmail.com>
Tue, 28 Apr 2009 13:25:43 +0000 (10:25 -0300)
Cython/Compiler/Nodes.py
Cython/Compiler/Options.py
tests/run/always_allow_keywords_T295.pyx [new file with mode: 0644]

index 1638189d1425930eb14e86423dbe08cc1b8dc2f0..b6c7f72c42a6b90e7a7287cd6b10683273847703 100644 (file)
@@ -1691,9 +1691,11 @@ class DefNode(FuncDefNode):
 
     def analyse_signature(self, env):
         any_type_tests_needed = 0
-        # Use the simpler calling signature for zero- and one-argument functions.
-        if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
-            if self.entry.signature is TypeSlots.pyfunction_signature and Options.optimize_simple_methods:
+        if self.entry.is_special:
+            self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
+        elif not env.directives['always_allow_keywords'] and not (self.star_arg or self.starstar_arg):
+            # Use the simpler calling signature for zero- and one-argument functions.
+            if self.entry.signature is TypeSlots.pyfunction_signature:
                 if len(self.args) == 0:
                     self.entry.signature = TypeSlots.pyfunction_noargs
                 elif len(self.args) == 1:
@@ -1705,8 +1707,6 @@ class DefNode(FuncDefNode):
                 elif len(self.args) == 2:
                     if self.args[1].default is None and not self.args[1].kw_only:
                         self.entry.signature = TypeSlots.ibinaryfunc
-        elif self.entry.is_special:
-            self.entry.trivial_signature = len(self.args) == 1 and not (self.star_arg or self.starstar_arg)
         sig = self.entry.signature
         nfixed = sig.num_fixed_args()
         for i in range(nfixed):
index 286b143c7763a71754c00d306cc2d61cbcb0ece5..06f7024475bf48f8450f62b372dd287435bdc8ae 100644 (file)
@@ -45,11 +45,6 @@ lookup_module_cpdef = 0
 # WARNING: This is a work in progress, may currently segfault.
 init_local_none = 1
 
-# Optimize no argument and one argument methods by using the METH_O and METH_NOARGS
-# calling conventions. These are faster calling conventions, but disallow the use of 
-# keywords (which, admittedly, are of little use in these cases). 
-optimize_simple_methods = 1
-
 # Append the c file and line number to the traceback for exceptions. 
 c_line_in_traceback = 1
 
@@ -68,6 +63,7 @@ option_defaults = {
     'auto_cpdef': False,
     'cdivision': True,  # Will be False in 0.12
     'cdivision_warnings': False,
+    'always_allow_keywords': False,
 }
 
 # Override types possibilities above, if needed
diff --git a/tests/run/always_allow_keywords_T295.pyx b/tests/run/always_allow_keywords_T295.pyx
new file mode 100644 (file)
index 0000000..3ead814
--- /dev/null
@@ -0,0 +1,60 @@
+__doc__ = """
+>>> func1(None)
+>>> func1(*[None])
+>>> func1(arg=None)
+Traceback (most recent call last):
+...
+TypeError: func1() takes no keyword arguments
+>>> func2(None)
+>>> func2(*[None])
+>>> func2(arg=None)
+Traceback (most recent call last):
+...
+TypeError: func2() takes no keyword arguments
+>>> func3(None)
+>>> func3(*[None])
+>>> func3(arg=None)
+
+>>> A().meth1(None)
+>>> A().meth1(*[None])
+>>> A().meth1(arg=None)
+Traceback (most recent call last):
+...
+TypeError: meth1() takes no keyword arguments
+>>> A().meth2(None)
+>>> A().meth2(*[None])
+>>> A().meth2(arg=None)
+Traceback (most recent call last):
+...
+TypeError: meth2() takes no keyword arguments
+>>> A().meth3(None)
+>>> A().meth3(*[None])
+>>> A().meth3(arg=None)
+"""
+
+cimport cython
+
+
+def func1(arg):
+    pass
+
+@cython.always_allow_keywords(False)
+def func2(arg):
+    pass
+
+@cython.always_allow_keywords(True)
+def func3(arg):
+    pass
+
+cdef class A:
+
+    def meth1(self, arg):
+        pass
+
+    @cython.always_allow_keywords(False)
+    def meth2(self, arg):
+        pass
+
+    @cython.always_allow_keywords(True)
+    def meth3(self, arg):
+        pass