[pypy-commit] pypy py3.5: Follow-up for 0146779efba0: don't mask the original TypeError in

arigo pypy.commits at gmail.com
Thu Dec 15 08:57:19 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r89069:76dcc5502332
Date: 2016-12-15 14:55 +0100
http://bitbucket.org/pypy/pypy/changeset/76dcc5502332/

Log:	Follow-up for 0146779efba0: don't mask the original TypeError in
	more general cases (but only on Python 3.x)

diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -92,7 +92,7 @@
             args_w = space.fixedview(w_stararg)
         except OperationError as e:
             if (e.match(space, space.w_TypeError) and
-                    not space.is_generator(w_stararg)):
+                    not space.is_iterable(w_stararg)):
                 raise oefmt(space.w_TypeError,
                             "argument after * must be an iterable, not %T",
                             w_stararg)
diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -878,6 +878,21 @@
         else:
             assert False, "Expected TypeError"
 
+    def test_call_iter_dont_eat_typeerror(self):
+        # same as test_cpython_issue4806, not only for generators
+        # (only for 3.x, on CPython 2.7 this case still eats the
+        # TypeError and replaces it with "argument after * ...")
+        class X:
+            def __iter__(self):
+                raise TypeError("myerror")
+        def f():
+            pass
+        e = raises(TypeError, "f(*42)")
+        assert str(e.value).endswith(
+            "argument after * must be an iterable, not int")
+        e = raises(TypeError, "f(*X())")
+        assert str(e.value) == "myerror"
+
     def test_keyword_arg_after_keywords_dict(self):
         """
         def f(x, y):
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -272,6 +272,15 @@
             raise oefmt(space.w_ValueError, "__len__() should return >= 0")
         return result
 
+    def is_iterable(space, w_obj):
+        w_descr = space.lookup(w_obj, '__iter__')
+        if w_descr is None:
+            if space.type(w_obj).flag_map_or_seq != 'M':
+                w_descr = space.lookup(w_obj, '__getitem__')
+            if w_descr is None:
+                return False
+        return True
+
     def iter(space, w_obj):
         w_descr = space.lookup(w_obj, '__iter__')
         if w_descr is None:


More information about the pypy-commit mailing list