changeset 705:1ee2ec866741

fix #20464: raises “TypeError: '_Yes' object is not iterable” on list inference
author Sylvain Thénault <sylvain.thenault@logilab.fr>
date Tue, 23 Mar 2010 09:47:19 +0100
parents 89ad40f83a7b
children d31d479ed4a1
files ChangeLog protocols.py test/unittest_inference.py
diffstat 3 files changed, 43 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Mar 22 18:23:24 2010 +0100
+++ b/ChangeLog	Tue Mar 23 09:47:19 2010 +0100
@@ -4,6 +4,8 @@
 --  
 
 2010-03-22 -- 0.20.0
+    * fix #20464: raises “TypeError: '_Yes' object is not iterable” on list inference
+
     * fix #19882: pylint hangs
 
     * fix #20759: crash on pyreverse UNARY_OP_METHOD KeyError '~'
@@ -22,8 +24,10 @@
     * Ned Batchelder patch to properly import eggs with Windows line
       endings.  This fixes a problem with pylint not being able to
       import setuptools.
+
     * Winfried Plapper patches fixing .op attribute value for AugAssign nodes,
       visit_ifexp in nodes_as_string
+
     * Edward K. Ream / Tom Fleck patch closes #19641 (maximum recursion depth
       exceeded" messages w/ python 2.6), see https://bugs.launchpad.net/pylint/+bug/456870
 
--- a/protocols.py	Mon Mar 22 18:23:24 2010 +0100
+++ b/protocols.py	Tue Mar 23 09:47:19 2010 +0100
@@ -107,13 +107,16 @@
     for other in other.infer(context):
         if isinstance(other, self.__class__) and operator == '+':
             node = self.__class__()
-            elts = [n for elt in self.elts for n in elt.infer(context)]
-            elts += [n for elt in other.elts for n in elt.infer(context)]
+            elts = [n for elt in self.elts for n in elt.infer(context)
+                    if not n is YES]
+            elts += [n for elt in other.elts for n in elt.infer(context)
+                     if not n is YES]
             node.elts = elts
             yield node
         elif isinstance(other, nodes.Const) and operator == '*':
             node = self.__class__()
-            elts = [n for elt in self.elts for n in elt.infer(context)] * other.value
+            elts = [n for elt in self.elts for n in elt.infer(context)
+                    if not n is YES] * other.value
             node.elts = elts
             yield node
         elif isinstance(other, Instance) and not isinstance(other, nodes.Const):
--- a/test/unittest_inference.py	Mon Mar 22 18:23:24 2010 +0100
+++ b/test/unittest_inference.py	Tue Mar 23 09:47:19 2010 +0100
@@ -1056,5 +1056,38 @@
                 break
         else:
             self.fail('expected to find an instance of Application in %s' % infered)
+
+    def test_list_inference(self):
+        """#20464"""
+        code = '''
+import optparse
+
+A = []
+B = []
+
+def test():
+  xyz = [
+    "foobar=%s" % options.ca,
+  ] + A + B
+
+  if options.bind is not None:
+    xyz.append("bind=%s" % options.bind)
+  return xyz
+
+def main():
+  global options
+
+  parser = optparse.OptionParser()
+  (options, args) = parser.parse_args()
+
+Z = test()
+        '''
+        astng = builder.string_build(code, __name__, __file__)
+        infered = list(astng['Z'].infer())
+        self.assertEquals(len(infered), 1, infered)
+        self.assertIsInstance(infered[0], Instance)
+        self.assertIsInstance(infered[0]._proxied, nodes.Class)
+        self.assertEquals(infered[0]._proxied.name, 'list')
+
 if __name__ == '__main__':
     unittest_main()