diff options
-rw-r--r-- | astroid/bases.py | 11 | ||||
-rw-r--r-- | astroid/node_classes.py | 15 | ||||
-rw-r--r-- | astroid/objects.py | 3 | ||||
-rw-r--r-- | astroid/tests/unittest_inference.py | 21 |
4 files changed, 40 insertions, 10 deletions
diff --git a/astroid/bases.py b/astroid/bases.py index 55f07ec0..3c79af09 100644 --- a/astroid/bases.py +++ b/astroid/bases.py @@ -711,16 +711,7 @@ class NodeNG(object): * YES: the inference engine is uncertain of the node's value. """ - context = InferenceContext() - try: - values = [inferred.bool_value() - for inferred in self.infer(context=context)] - except InferenceError: - return YES - if len(set(values)) != len(values): - # Too many inferred values, can't tell. - return YES - return values[0] + return YES class Statement(NodeNG): diff --git a/astroid/node_classes.py b/astroid/node_classes.py index ef46bab1..d8670e42 100644 --- a/astroid/node_classes.py +++ b/astroid/node_classes.py @@ -584,6 +584,9 @@ class Dict(NodeNG, Instance): # IndexError. Let's leave it like that for now. raise IndexError(lookup_key) + def bool_value(self): + return bool(self.items) + class Discard(Statement): """class representing a Discard node""" @@ -594,6 +597,9 @@ class Discard(Statement): class Ellipsis(NodeNG): # pylint: disable=redefined-builtin """class representing an Ellipsis node""" + def bool_value(self): + return True + class EmptyNode(NodeNG): """class representing an EmptyNode node""" @@ -737,6 +743,9 @@ class List(NodeNG, Instance, ParentAssignTypeMixin): def itered(self): return self.elts + + def bool_value(self): + return bool(self.elts) class Nonlocal(Statement): @@ -802,6 +811,9 @@ class Set(NodeNG, Instance, ParentAssignTypeMixin): def itered(self): return self.elts + def bool_value(self): + return bool(self.elts) + class Slice(NodeNG): """class representing a Slice node""" @@ -881,6 +893,9 @@ class Tuple(NodeNG, Instance, ParentAssignTypeMixin): def itered(self): return self.elts + def bool_value(self): + return bool(self.elts) + class UnaryOp(NodeNG): """class representing an UnaryOp node""" diff --git a/astroid/objects.py b/astroid/objects.py index a1c1da10..b3f3caea 100644 --- a/astroid/objects.py +++ b/astroid/objects.py @@ -66,6 +66,9 @@ class FrozenSet(NodeNG, Instance, ParentAssignTypeMixin): builtins = MANAGER.astroid_cache[BUILTINS] return builtins.getattr('frozenset')[0] + def bool_value(self): + return bool(self.elts) + class Super(NodeNG): """Proxy class over a super call. diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py index 7e3c41dd..08f5a9eb 100644 --- a/astroid/tests/unittest_inference.py +++ b/astroid/tests/unittest_inference.py @@ -1978,6 +1978,22 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase): for node in ast_nodes: self.assertEqual(node.type_errors(), []) + def test_bool_value_recursive(self): + pairs = [ + ('{}', False), + ('{1:2}', True), + ('()', False), + ('(1, 2)', True), + ('[]', False), + ('[1,2]', True), + ('frozenset()', False), + ('frozenset((1, 2))', True), + ] + for code, expected in pairs: + node = test_utils.extract_node(code) + inferred = next(node.infer()) + self.assertEqual(inferred.bool_value(), expected) + def test_bool_value(self): # Verify the truth value of nodes. module = test_utils.build_module(''' @@ -1996,11 +2012,14 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase): bound_method = instance.method def generator_func(): yield + def true_value(): + return True generator = generator_func() name = generator bin_op = 1 + 2 bool_op = x and y callfunc = test() + good_callfunc = true_value() compare = 2 < 3 const_str_true = 'testconst' const_str_false = '' @@ -2035,6 +2054,8 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase): self.assertEqual(bool_op.bool_value(), YES) callfunc = module['callfunc'].parent.value self.assertEqual(callfunc.bool_value(), YES) + good_callfunc = next(module['good_callfunc'].infer()) + self.assertTrue(good_callfunc.bool_value()) compare = module['compare'].parent.value self.assertEqual(compare.bool_value(), YES) |