summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2015-10-03 13:40:40 +0300
committerClaudiu Popa <pcmanticore@gmail.com>2015-10-03 13:40:40 +0300
commit670427f3bfc97c3a6a50689c918e3a87f1729dbb (patch)
treeb0ab9bf4e07a1a07ba67168c9d0686cc54f92d6d
parente61258e7be8330ae4e0dfd75eb3d7210f40383e0 (diff)
downloadastroid-670427f3bfc97c3a6a50689c918e3a87f1729dbb.tar.gz
Ignore non-callables when looking for special method implementations of bool methods
This commit verifies what a special method actually is and if it's not a callable, then we return an YES object, since there's a big chance to not make sense of the instance's boolean value.
-rw-r--r--astroid/bases.py2
-rw-r--r--astroid/tests/unittest_inference.py21
2 files changed, 22 insertions, 1 deletions
diff --git a/astroid/bases.py b/astroid/bases.py
index 3656102..3ed52bf 100644
--- a/astroid/bases.py
+++ b/astroid/bases.py
@@ -126,6 +126,8 @@ def _infer_method_result_truth(instance, method_name, context):
# its return's truth value.
meth = next(instance.igetattr(method_name, context=context), None)
if meth and hasattr(meth, 'infer_call_result'):
+ if not meth.callable():
+ return util.YES
for value in meth.infer_call_result(instance, context=context):
if value is util.YES:
return value
diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py
index 093b076..644e282 100644
--- a/astroid/tests/unittest_inference.py
+++ b/astroid/tests/unittest_inference.py
@@ -3324,16 +3324,35 @@ class TestBool(unittest.TestCase):
class TrueClass:
def {method}(self):
return True
+ class C(object):
+ def __call__(self):
+ return False
+ class B(object):
+ {method} = C()
bool(FalseClass) #@
bool(TrueClass) #@
bool(FalseClass()) #@
bool(TrueClass()) #@
+ bool(B()) #@
'''.format(method=BOOL_SPECIAL_METHOD))
- expected = [True, True, False, True]
+ expected = [True, True, False, True, False]
for node, expected_value in zip(ast_nodes, expected):
inferred = next(node.infer())
self.assertEqual(inferred.value, expected_value)
+ def test_bool_instance_not_callable(self):
+ ast_nodes = test_utils.extract_node('''
+ class BoolInvalid(object):
+ {method} = 42
+ class LenInvalid(object):
+ __len__ = "a"
+ bool(BoolInvalid()) #@
+ bool(LenInvalid()) #@
+ '''.format(method=BOOL_SPECIAL_METHOD))
+ for node in ast_nodes:
+ inferred = next(node.infer())
+ self.assertEqual(inferred, util.YES)
+
class TestType(unittest.TestCase):