[pypy-svn] r77542 - in pypy/branch/fast-forward/pypy/interpreter: . test

afa at codespeak.net afa at codespeak.net
Fri Oct 1 22:45:28 CEST 2010


Author: afa
Date: Fri Oct  1 22:45:27 2010
New Revision: 77542

Modified:
   pypy/branch/fast-forward/pypy/interpreter/argument.py
   pypy/branch/fast-forward/pypy/interpreter/test/test_function.py
Log:
**kwargs now accepts any mapping


Modified: pypy/branch/fast-forward/pypy/interpreter/argument.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/argument.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/argument.py	Fri Oct  1 22:45:27 2010
@@ -149,14 +149,25 @@
         # unpack the ** arguments
         if w_starstararg is not None:
             space = self.space
-            if not space.is_true(space.isinstance(w_starstararg, space.w_dict)):
-                raise OperationError(space.w_TypeError,
-                                     space.wrap("argument after ** must be "
-                                                "a dictionary"))
-            keywords_w = [None] * space.int_w(space.len(w_starstararg))
-            keywords = [None] * space.int_w(space.len(w_starstararg))
+            if space.isinstance_w(w_starstararg, space.w_dict):
+                keys_w = space.unpackiterable(w_starstararg)
+            else:
+                try:
+                    w_keys = space.call_method(w_starstararg, "keys")
+                except OperationError, e:
+                    if e.match(space, space.w_AttributeError):
+                        w_type = space.type(w_starstararg)
+                        typename = w_type.getname(space, '?')
+                        raise OperationError(
+                            space.w_TypeError,
+                            space.wrap("argument after ** must be "
+                                       "a mapping, not %s" % (typename,)))
+                    raise
+                keys_w = space.unpackiterable(w_keys)
+            keywords_w = [None] * len(keys_w)
+            keywords = [None] * len(keys_w)
             i = 0
-            for w_key in space.unpackiterable(w_starstararg):
+            for w_key in keys_w:
                 try:
                     key = space.str_w(w_key)
                 except OperationError, e:

Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_function.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/test/test_function.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/test/test_function.py	Fri Oct  1 22:45:27 2010
@@ -164,6 +164,21 @@
         raises(
             TypeError, func, 42, {'arg1': 23})
 
+    def test_kwargs_nondict_mapping(self):
+        class Mapping:
+            def keys(self):
+                return ('a', 'b')
+            def __getitem__(self, key):
+                return key
+        def func(arg1, **kw):
+            return arg1, kw
+        res = func(23, **Mapping())
+        assert res[0] == 23
+        assert res[1] == {'a': 'a', 'b': 'b'}
+        error = raises(TypeError, lambda: func(42, **[]))
+        assert error.value.message == ('argument after ** must be a mapping, '
+                                       'not list')
+
     def test_default_arg(self):
         def func(arg1,arg2=42):
             return arg1, arg2



More information about the Pypy-commit mailing list