[Python-checkins] r53878 - sandbox/trunk/pep362/pep362.py sandbox/trunk/pep362/test_pep362.py

brett.cannon python-checkins at python.org
Fri Feb 23 23:39:55 CET 2007


Author: brett.cannon
Date: Fri Feb 23 23:39:52 2007
New Revision: 53878

Modified:
   sandbox/trunk/pep362/pep362.py
   sandbox/trunk/pep362/test_pep362.py
Log:
Add support for keyword-only arguments in Signature.


Modified: sandbox/trunk/pep362/pep362.py
==============================================================================
--- sandbox/trunk/pep362/pep362.py	(original)
+++ sandbox/trunk/pep362/pep362.py	Fri Feb 23 23:39:52 2007
@@ -81,13 +81,17 @@
         """Initialize from a function or method object."""
         if hasattr(func, 'im_func'):
             func = func.im_func
+        func_code = func.func_code
+
         self.name = func.__name__
 
         argspec = inspect.getargspec(func)
 
+        # Variable parameters.
         self.var_args = argspec[1] if (argspec[1] is not None)  else ''
         self.var_kw_args = argspec[2] if (argspec[2] is not None) else ''
 
+        # Non-keyword-only arguments.
         arg_count = len(argspec[0])
         defaults_start = (arg_count - len(argspec[3])
                             if argspec[3] else arg_count)
@@ -102,6 +106,23 @@
             else:
                 parameters.append(Parameter(arg_name, index, False))
 
+        # Keyword-only arguments.
+        if hasattr(func_code, 'co_kwonlyargcount'):
+            non_keyword_count = func_code.co_argcount
+            keyword_count = func_code.co_kwonlyargcount
+            keyword_only_params = func_code.co_varnames[non_keyword_count:
+                                            (non_keyword_count+keyword_count)]
+            for index, param_name in enumerate(keyword_only_params):
+                has_default = False
+                default_value = None
+                if func.func_kwdefaults and param_name in func.func_kwdefaults:
+                    has_default = True
+                    default_value = func.func_kwdefaults[param_name]
+                parameters.append(Parameter(param_name,
+                                            index+non_keyword_count,
+                                            has_default, default_value,
+                                            keyword_only=True))
+
         self.parameters = tuple(parameters)
 
     @classmethod

Modified: sandbox/trunk/pep362/test_pep362.py
==============================================================================
--- sandbox/trunk/pep362/test_pep362.py	(original)
+++ sandbox/trunk/pep362/test_pep362.py	Fri Feb 23 23:39:52 2007
@@ -3,6 +3,16 @@
 import unittest
 from test import test_support
 import pep362_fodder
+from sys import version_info
+if version_info[0] >= 3:
+    import pep362_py3k_fodder
+
+def py3k_test(fxn):
+    if version_info[0] >= 3:
+        return fxn
+    else:
+        return lambda self: self
+
 
 class ParameterObjectTests(unittest.TestCase):
 
@@ -52,14 +62,6 @@
         self.failUnlessEqual(param.has_annotation, True)
         self.failUnlessEqual(param.annotation, annotation)
 
-    def test_str(self):
-        # Test __str__().
-        name = "X"
-        param = pep362.Parameter(name, 0, False)
-        self.failUnlessEqual(name, str(param))
-        default_value = 42
-        param = pep362.Parameter(name, 0, True, default_value)
-        self.failUnlessEqual("%s=%s" % (name, default_value), str(param))
 
 class SignatureObjectTests(unittest.TestCase):
 
@@ -89,6 +91,7 @@
         self.failUnlessEqual('', sig.var_kw_args)
 
     def test_parameter_positional(self):
+        # A function with positional arguments should work.
         sig = pep362.Signature(pep362_fodder.no_default_args)
         self.failUnlessEqual('no_default_args', sig.name)
         param = sig.parameters[0]
@@ -98,6 +101,7 @@
         self.failUnless(not hasattr(param, 'default_value'))
 
     def test_parameter_default(self):
+        # Default parameters for a function should work.
         sig = pep362.Signature(pep362_fodder.default_args)
         self.failUnlessEqual('default_args', sig.name)
         param = sig.parameters[0]
@@ -107,6 +111,7 @@
         self.failUnlessEqual(42, param.default_value)
 
     def test_parameter_tuple(self):
+        # A function with a tuple as a parameter should work.
         sig = pep362.Signature(pep362_fodder.tuple_args)
         self.failUnlessEqual('tuple_args', sig.name)
         param = sig.parameters[0]
@@ -117,6 +122,7 @@
         self.failUnless(not hasattr(param, 'default_value'))
 
     def test_parameter_tuple_default(self):
+        # A default argument for a tuple parameter needs to work.
         sig = pep362.Signature(pep362_fodder.default_tuple_args)
         self.failUnlessEqual('default_tuple_args', sig.name)
         param = sig.parameters[0]
@@ -125,11 +131,33 @@
         self.failUnless(param.has_default)
         self.failUnlessEqual((1, (2,)), param.default_value)
 
-    def test_positioning(self):
+    def test_getitem(self):
+        # Signature objects should have __getitem__ defined.
         sig = pep362.Signature(pep362_fodder.all_args)
         param = sig.parameters[2]
         self.failUnlessEqual('d', param.name)
 
+    @py3k_test
+    def test_keyword_only(self):
+        # Is a function containing keyword-only parameters handled properly?
+        sig = pep362.Signature(pep362_py3k_fodder.keyword_only)
+        param = sig.parameters[0]
+        self.failUnlessEqual(param.name, 'a')
+        self.failUnless(param.keyword_only)
+        self.failUnlessEqual(param.position, 0)
+
+    @py3k_test
+    def test_keyword_only_default(self):
+        # Default arguments can work for keyword-only parameters.
+        sig = pep362.Signature(pep362_py3k_fodder.keyword_only_default)
+        param = sig.parameters[0]
+        self.failUnlessEqual(param.name, 'a')
+        self.failUnless(param.keyword_only)
+        self.failUnlessEqual(param.position, 0)
+        self.failUnless(param.has_default)
+        self.failUnlessEqual(param.default_value, 42)
+
+
     def test_signature(self):
         def fresh_func():
             pass
@@ -144,27 +172,6 @@
         sig = pep362.signature(FreshClass.fresh_method)
         self.failUnlessEqual(sig, FreshClass.fresh_method.im_func.__signature__)
 
-    def test_str(self):
-        # Test __str__().
-        sig = pep362.Signature(pep362_fodder.no_args)
-        self.failUnlessEqual("no_args()", str(sig))
-        sig = pep362.Signature(pep362_fodder.var_args)
-        self.failUnlessEqual("var_args(*args)", str(sig))
-        sig = pep362.Signature(pep362_fodder.var_kw_args)
-        self.failUnlessEqual("var_kw_args(**kwargs)", str(sig))
-        sig = pep362.Signature(pep362_fodder.default_args)
-        self.failUnlessEqual("default_args(a=42)", str(sig))
-        sig = pep362.Signature(pep362_fodder.no_default_args)
-        self.failUnlessEqual("no_default_args(a)", str(sig))
-        sig = pep362.Signature(pep362_fodder.tuple_args)
-        self.failUnlessEqual("tuple_args((a, (b,)))", str(sig))
-        sig = pep362.Signature(pep362_fodder.default_tuple_args)
-        self.failUnlessEqual("default_tuple_args((a, (b,))=(1, (2,)))",
-                             str(sig))
-        sig = pep362.Signature(pep362_fodder.all_args)
-        self.failUnlessEqual("all_args(a, (b, (c,)), d=0, "
-                               "(e, (f,))=(1, (2,)), *g, **h)",
-                             str(sig))
 
 class SignatureBindTests(unittest.TestCase):
 


More information about the Python-checkins mailing list