diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2015-11-23 13:44:11 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2015-11-23 13:44:11 +0200 |
commit | 02bdefc5b90d8a93436996f183e63e2a9f85706d (patch) | |
tree | a8ffaf01f0cbdbd5258fb20606852df39f04bde4 /astroid/tests | |
parent | a36fefbd83d2cc021fce2793ffbfe25d2720a57e (diff) | |
download | astroid-02bdefc5b90d8a93436996f183e63e2a9f85706d.tar.gz |
Handle the cases when a List can contain Uninferable as its elements
This can happen for instance when the list contains objects which
weren't inferable in the first place. There were a bunch of places
affected by this bug: unpack_infer, the inference of list additions
and the handling of the namedtuple's fields.
Diffstat (limited to 'astroid/tests')
-rw-r--r-- | astroid/tests/unittest_brain.py | 11 | ||||
-rw-r--r-- | astroid/tests/unittest_inference.py | 14 | ||||
-rw-r--r-- | astroid/tests/unittest_utils.py | 142 |
3 files changed, 102 insertions, 65 deletions
diff --git a/astroid/tests/unittest_brain.py b/astroid/tests/unittest_brain.py index 096847e..fbdfbb1 100644 --- a/astroid/tests/unittest_brain.py +++ b/astroid/tests/unittest_brain.py @@ -89,6 +89,7 @@ class HashlibTest(unittest.TestCase): class NamedTupleTest(unittest.TestCase): + def test_namedtuple_base(self): klass = test_utils.extract_node(""" from collections import namedtuple @@ -150,6 +151,16 @@ class NamedTupleTest(unittest.TestCase): for name, attr in inferred.instance_attrs.items(): self.assertEqual(attr[0].attrname, name) + def test_namedtuple_uninferable_fields(self): + node = test_utils.extract_node(''' + x = [A] * 2 + from collections import namedtuple + l = namedtuple('a', x) + l(1) + ''') + inferred = next(node.infer()) + self.assertIs(util.Uninferable, inferred) + class ModuleExtenderTest(unittest.TestCase): def testExtensionModules(self): diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py index 98a4daf..853149a 100644 --- a/astroid/tests/unittest_inference.py +++ b/astroid/tests/unittest_inference.py @@ -1321,7 +1321,8 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase): ast = parse(code, __name__) inferred = next(ast['Z'].infer()) self.assertIsInstance(inferred, nodes.List) - self.assertEqual(len(inferred.elts), 0) + self.assertEqual(len(inferred.elts), 1) + self.assertIs(inferred.elts[0], util.Uninferable) def test__new__(self): code = ''' @@ -2343,6 +2344,17 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase): inferred = next(node.infer()) self.assertEqual(inferred.value, expected) + def test_binop_list_with_elts(self): + ast_node = test_utils.extract_node(''' + x = [A] * 1 + [1] + x + ''') + inferred = next(ast_node.infer()) + self.assertIsInstance(inferred, nodes.List) + self.assertEqual(len(inferred.elts), 2) + self.assertIsInstance(inferred.elts[0], nodes.Const) + self.assertIs(inferred.elts[1], util.Uninferable) + def test_binop_same_types(self): ast_nodes = test_utils.extract_node(''' class A(object): diff --git a/astroid/tests/unittest_utils.py b/astroid/tests/unittest_utils.py index 999f7ed..e6dc380 100644 --- a/astroid/tests/unittest_utils.py +++ b/astroid/tests/unittest_utils.py @@ -1,4 +1,4 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2015 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of astroid. @@ -17,85 +17,99 @@ # with astroid. If not, see <http://www.gnu.org/licenses/>. import unittest -from astroid import builder, nodes -from astroid.node_classes import are_exclusive +from astroid import builder +from astroid import nodes +from astroid import node_classes +from astroid import test_utils +from astroid import util as astroid_util -builder = builder.AstroidBuilder() -class AreExclusiveTC(unittest.TestCase): +class InferenceUtil(unittest.TestCase): + def test_not_exclusive(self): - astroid = builder.string_build(""" -x = 10 -for x in range(5): - print (x) + module = builder.parse(""" + x = 10 + for x in range(5): + print (x) -if x > 0: - print ('#' * x) + if x > 0: + print ('#' * x) """, __name__, __file__) - xass1 = astroid.locals['x'][0] + xass1 = module.locals['x'][0] assert xass1.lineno == 2 - xnames = [n for n in astroid.nodes_of_class(nodes.Name) if n.name == 'x'] + xnames = [n for n in module.nodes_of_class(nodes.Name) if n.name == 'x'] assert len(xnames) == 3 assert xnames[1].lineno == 6 - self.assertEqual(are_exclusive(xass1, xnames[1]), False) - self.assertEqual(are_exclusive(xass1, xnames[2]), False) + self.assertEqual(node_classes.are_exclusive(xass1, xnames[1]), False) + self.assertEqual(node_classes.are_exclusive(xass1, xnames[2]), False) def test_if(self): - astroid = builder.string_build(''' - -if 1: - a = 1 - a = 2 -elif 2: - a = 12 - a = 13 -else: - a = 3 - a = 4 + module = builder.parse(''' + if 1: + a = 1 + a = 2 + elif 2: + a = 12 + a = 13 + else: + a = 3 + a = 4 ''') - a1 = astroid.locals['a'][0] - a2 = astroid.locals['a'][1] - a3 = astroid.locals['a'][2] - a4 = astroid.locals['a'][3] - a5 = astroid.locals['a'][4] - a6 = astroid.locals['a'][5] - self.assertEqual(are_exclusive(a1, a2), False) - self.assertEqual(are_exclusive(a1, a3), True) - self.assertEqual(are_exclusive(a1, a5), True) - self.assertEqual(are_exclusive(a3, a5), True) - self.assertEqual(are_exclusive(a3, a4), False) - self.assertEqual(are_exclusive(a5, a6), False) + a1 = module.locals['a'][0] + a2 = module.locals['a'][1] + a3 = module.locals['a'][2] + a4 = module.locals['a'][3] + a5 = module.locals['a'][4] + a6 = module.locals['a'][5] + self.assertEqual(node_classes.are_exclusive(a1, a2), False) + self.assertEqual(node_classes.are_exclusive(a1, a3), True) + self.assertEqual(node_classes.are_exclusive(a1, a5), True) + self.assertEqual(node_classes.are_exclusive(a3, a5), True) + self.assertEqual(node_classes.are_exclusive(a3, a4), False) + self.assertEqual(node_classes.are_exclusive(a5, a6), False) def test_try_except(self): - astroid = builder.string_build(''' -try: - def exclusive_func2(): - "docstring" -except TypeError: - def exclusive_func2(): - "docstring" -except: - def exclusive_func2(): - "docstring" -else: - def exclusive_func2(): - "this one redefine the one defined line 42" + module = builder.parse(''' + try: + def exclusive_func2(): + "docstring" + except TypeError: + def exclusive_func2(): + "docstring" + except: + def exclusive_func2(): + "docstring" + else: + def exclusive_func2(): + "this one redefine the one defined line 42" + ''') + f1 = module.locals['exclusive_func2'][0] + f2 = module.locals['exclusive_func2'][1] + f3 = module.locals['exclusive_func2'][2] + f4 = module.locals['exclusive_func2'][3] + self.assertEqual(node_classes.are_exclusive(f1, f2), True) + self.assertEqual(node_classes.are_exclusive(f1, f3), True) + self.assertEqual(node_classes.are_exclusive(f1, f4), False) + self.assertEqual(node_classes.are_exclusive(f2, f4), True) + self.assertEqual(node_classes.are_exclusive(f3, f4), True) + self.assertEqual(node_classes.are_exclusive(f3, f2), True) + + self.assertEqual(node_classes.are_exclusive(f2, f1), True) + self.assertEqual(node_classes.are_exclusive(f4, f1), False) + self.assertEqual(node_classes.are_exclusive(f4, f2), True) + def test_unpack_infer_uninferable_nodes(self): + node = test_utils.extract_node(''' + x = [A] * 1 + f = [x, [A] * 2] + f ''') - f1 = astroid.locals['exclusive_func2'][0] - f2 = astroid.locals['exclusive_func2'][1] - f3 = astroid.locals['exclusive_func2'][2] - f4 = astroid.locals['exclusive_func2'][3] - self.assertEqual(are_exclusive(f1, f2), True) - self.assertEqual(are_exclusive(f1, f3), True) - self.assertEqual(are_exclusive(f1, f4), False) - self.assertEqual(are_exclusive(f2, f4), True) - self.assertEqual(are_exclusive(f3, f4), True) - self.assertEqual(are_exclusive(f3, f2), True) + inferred = next(node.infer()) + unpacked = list(node_classes.unpack_infer(inferred)) + self.assertEqual(len(unpacked), 3) + self.assertTrue(all(elt is astroid_util.Uninferable + for elt in unpacked)) - self.assertEqual(are_exclusive(f2, f1), True) - self.assertEqual(are_exclusive(f4, f1), False) - self.assertEqual(are_exclusive(f4, f2), True) if __name__ == '__main__': unittest.main() |