[Python-checkins] r59028 - in sandbox/trunk/pep362: pep362.py tests/test_pep362.py

brett.cannon python-checkins at python.org
Sat Nov 17 04:47:49 CET 2007


Author: brett.cannon
Date: Sat Nov 17 04:47:49 2007
New Revision: 59028

Modified:
   sandbox/trunk/pep362/pep362.py
   sandbox/trunk/pep362/tests/test_pep362.py
Log:
Add __getitem__ to Signature along with __iter__.  This removes the need for
Signature.parameters.


Modified: sandbox/trunk/pep362/pep362.py
==============================================================================
--- sandbox/trunk/pep362/pep362.py	(original)
+++ sandbox/trunk/pep362/pep362.py	Sat Nov 17 04:47:49 2007
@@ -1,4 +1,5 @@
 import inspect
+from operator import attrgetter
 
 
 class BindError(TypeError):
@@ -50,8 +51,6 @@
     """Object to represent the signature of a function/method.
 
     Attributes:
-    * parameters
-        Sequence of Parameter objects.
     * name
         Name of the function/method.
     * var_args
@@ -90,7 +89,7 @@
         except AttributeError:
             # Needed only for tuple parameters.
             argspec = inspect.getargspec(func)
-        parameters = []
+        parameters = {}
 
         # Parameter information.
         pos_count = func_code.co_argcount
@@ -118,7 +117,7 @@
             has_annotation, annotation = self._find_annotation(func, name)
             param = Parameter(name, index, has_default=False,
                     has_annotation=has_annotation, annotation=annotation)
-            parameters.append(param)
+            parameters[name] = param
         # ... w/ defaults.
         for offset, name in enumerate(positional[non_default_count:]):
             name = self._convert_name(name)
@@ -128,7 +127,7 @@
                                 has_default=True, default_value=default_value,
                                 has_annotation=has_annotation,
                                 annotation=annotation)
-            parameters.append(param)
+            parameters[name] = param
         # Keyword-only parameters.
         for offset, name in enumerate(keyword_only):
             has_annotation, annotation = self._find_annotation(func, name)
@@ -143,7 +142,7 @@
                                 default_value=default_value,
                                 has_annotation=has_annotation,
                                 annotation=annotation)
-            parameters.append(param)
+            parameters[name] = param
         # Variable parameters.
         index = pos_count + keyword_only_count
         self.var_annotations = dict()
@@ -168,13 +167,19 @@
         else:
             self.var_kw_args = ''
 
-        self.parameters = tuple(parameters)
+        self._parameters = parameters
 
         # Return annotation.
         if hasattr(func, '__annotations__'):
             if 'return' in func.__annotations__:
                 self.return_annotation = func.__annotations__['return']
 
+    def __getitem__(self, key):
+        return self._parameters[key]
+
+    def __iter__(self):
+        return iter(sorted(self._parameters.values(), key=attrgetter('position')))
+
     def _find_annotation(self, func, name):
         """Return True if an annotation exists for the named parameter along
         with its annotation, else return False and None."""
@@ -207,14 +212,14 @@
         positional = []
         keyword_only = {}
 
-        for param in self.parameters:
+        for param in self:
             if not param.keyword_only:
                 positional.append(param)
             else:
                 keyword_only[param.name] = param
 
         # Positional arguments.
-        if not self.parameters and args and self.var_args:
+        if not self._parameters and args and self.var_args:
             bindings[self.var_args] = args
             args = tuple()
         for index, position_arg in enumerate(args[:]):

Modified: sandbox/trunk/pep362/tests/test_pep362.py
==============================================================================
--- sandbox/trunk/pep362/tests/test_pep362.py	(original)
+++ sandbox/trunk/pep362/tests/test_pep362.py	Sat Nov 17 04:47:49 2007
@@ -66,19 +66,34 @@
 
 class SignatureObjectTests(unittest.TestCase):
 
+    def test_getitem(self):
+        # __getitem__() should return the Parameter object for the name
+        # parameter.
+        sig = pep362.Signature(pep362_fodder.default_args)
+        self.failUnless(sig['a'])
+        param = sig['a']
+        self.failUnlessEqual(param.name, 'a')
+
+    def test_iter(self):
+        # The iterator should return all Parameter objects in the proper order.
+        sig = pep362.Signature(pep362_fodder.default_args)
+        params = list(sig)
+        self.failUnlessEqual(len(params), 1)
+        self.failUnlessEqual(params[0].name, 'a')
+
     def test_no_args(self):
         # Test a function with no arguments.
         sig = pep362.Signature(pep362_fodder.no_args)
         self.failUnlessEqual('no_args', sig.name)
         self.failUnless(not sig.var_args)
         self.failUnless(not sig.var_kw_args)
-        self.failUnlessEqual(0, len(sig.parameters))
+        self.failUnlessEqual(0, len(list(sig)))
 
     def test_var_args(self):
         # Test the var_args attribute.
         sig = pep362.Signature(pep362_fodder.var_args)
         self.failUnlessEqual('args', sig.var_args)
-        self.failUnlessEqual(0, len(sig.parameters))
+        self.failUnlessEqual(0, len(list(sig)))
         sig = pep362.Signature(pep362_fodder.no_args)
         self.failUnlessEqual('', sig.var_args)
 
@@ -87,7 +102,7 @@
         sig = pep362.Signature(pep362_fodder.var_kw_args)
         self.failUnlessEqual('var_kw_args', sig.name)
         self.failUnlessEqual('kwargs', sig.var_kw_args)
-        self.failUnlessEqual(0, len(sig.parameters))
+        self.failUnlessEqual(0, len(list(sig)))
         sig = pep362.Signature(pep362_fodder.no_args)
         self.failUnlessEqual('', sig.var_kw_args)
 
@@ -95,7 +110,7 @@
         # 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]
+        param = sig['a']
         self.failUnlessEqual('a', param.name)
         self.failUnlessEqual(0, param.position)
         self.failUnless(not hasattr(param, 'default_value'))
@@ -104,7 +119,7 @@
         # Default parameters for a function should work.
         sig = pep362.Signature(pep362_fodder.default_args)
         self.failUnlessEqual('default_args', sig.name)
-        param = sig.parameters[0]
+        param = sig['a']
         self.failUnlessEqual('a', param.name)
         self.failUnlessEqual(0, param.position)
         self.failUnlessEqual(42, param.default_value)
@@ -114,7 +129,7 @@
         # A function with a tuple as a parameter should work.
         sig = pep362.Signature(pep362_py2_fodder.tuple_args)
         self.failUnlessEqual('tuple_args', sig.name)
-        param = sig.parameters[0]
+        param = list(sig)[0]
         self.failUnless(isinstance(param.name, tuple))
         self.failUnlessEqual(('a', ('b',)), param.name)
         self.failUnlessEqual(0, param.position)
@@ -125,7 +140,7 @@
         # A default argument for a tuple parameter needs to work.
         sig = pep362.Signature(pep362_py2_fodder.default_tuple_args)
         self.failUnlessEqual('default_tuple_args', sig.name)
-        param = sig.parameters[0]
+        param = list(sig)[0]
         self.failUnlessEqual(('a', ('b',)), param.name)
         self.failUnlessEqual(0, param.position)
         self.failUnlessEqual((1, (2,)), param.default_value)
@@ -134,7 +149,7 @@
     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]
+        param = sig['a']
         self.failUnlessEqual(param.name, 'a')
         self.failUnless(param.keyword_only)
         self.failUnlessEqual(param.position, 0)
@@ -143,7 +158,7 @@
     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]
+        param = sig['a']
         self.failUnlessEqual(param.name, 'a')
         self.failUnless(param.keyword_only)
         self.failUnlessEqual(param.position, 0)
@@ -153,7 +168,7 @@
     def test_annotations(self):
         # Make sure the proper annotation is found.
         sig = pep362.Signature(pep362_py3k_fodder.arg_annotation)
-        param = sig.parameters[0]
+        param = sig['a']
         self.failUnlessEqual(param.name, 'a')
         self.failUnlessEqual(param.annotation, int)
 
@@ -161,7 +176,7 @@
     def test_annotations_default(self):
         # Annotations with a default value should work.
         sig = pep362.Signature(pep362_py3k_fodder.arg_annotation_default)
-        param = sig.parameters[0]
+        param = sig['a']
         self.failUnlessEqual(param.name, 'a')
         self.failUnlessEqual(param.annotation, int)
         self.failUnlessEqual(param.default_value, 42)
@@ -170,7 +185,7 @@
     def test_annotation_keyword_only(self):
         # Keyword-only parameters can have an annotation.
         sig = pep362.Signature(pep362_py3k_fodder.arg_annotation_keyword_only)
-        param = sig.parameters[0]
+        param = sig['a']
         self.failUnlessEqual(param.name, 'a')
         self.failUnlessEqual(param.annotation, int)
         self.failUnless(param.keyword_only)
@@ -279,8 +294,8 @@
                     (('b', ('c',)), 1, False, None),
                     ('d', 2, True, 0),
                     (('e', ('f',)), 3, True, (4, (5,))))
-        self.failUnlessEqual(len(sig.parameters), len(expect))
-        for param, check in zip(sig.parameters, expect):
+        self.failUnlessEqual(len(list(sig)), len(expect))
+        for param, check in zip(list(sig), expect):
             name, pos, has_default, default_value = check
             self.failUnlessEqual(param.name, name)
             self.failUnlessEqual(param.position, pos)
@@ -324,11 +339,11 @@
                     ('d', 1, False, True, 0, False, None),
                     ('g', 2, True, False, None, True, int),
                     ('h', 3, True, True, 8, True, int))
-        self.failUnlessEqual(len(sig.parameters), len(expected),
+        self.failUnlessEqual(len(list(sig)), len(expected),
                 "len(%r) != len(%r)" % ([param.name
-                                            for param in sig.parameters],
+                                            for param in sig],
                                         [expect[0] for expect in expected]))
-        for param, check in zip(sig.parameters, expected):
+        for param, check in zip(sig, expected):
             name, pos, kw_only, has_default, default, has_anno, anno = check
             self.failUnlessEqual(param.name, name)
             self.failUnlessEqual(param.position, pos)


More information about the Python-checkins mailing list