summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2015-11-29 22:11:22 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2015-12-29 16:36:39 +0200
commitc2590f59337ff742e503e4e2435467bea65c74f5 (patch)
tree3a518830893c6ed9a2745999f75bd7e773ce5a56
parentd8a87cc5055abe7f8a8a41222632b640cf89ed7f (diff)
downloadastroid-git-c2590f59337ff742e503e4e2435467bea65c74f5.tar.gz
Add support for handling Uninferable nodes when calling as_string
Some object, for instance List or Tuple can have, after inference, Uninferable as their elements, happening when their components weren't couldn't be inferred properly. This means that as_string needs to cope with expecting Uninferable nodes part of the other nodes coming for a string transformation. The patch adds a visit method in AsString and ``accept`` on Yes / Uninferable nodes. Closes issue #270.
-rw-r--r--astroid/as_string.py3
-rw-r--r--astroid/tests/unittest_nodes.py10
-rw-r--r--astroid/util.py6
3 files changed, 19 insertions, 0 deletions
diff --git a/astroid/as_string.py b/astroid/as_string.py
index 37dc77d5..d160b376 100644
--- a/astroid/as_string.py
+++ b/astroid/as_string.py
@@ -434,6 +434,9 @@ class AsStringVisitor(object):
def visit_super(self, node):
return node.parent.accept(self)
+ def visit_uninferable(self, node):
+ return str(node)
+
class AsStringVisitor3(AsStringVisitor):
"""AsStringVisitor3 overwrites some AsStringVisitor methods"""
diff --git a/astroid/tests/unittest_nodes.py b/astroid/tests/unittest_nodes.py
index 56f70571..ce8863b3 100644
--- a/astroid/tests/unittest_nodes.py
+++ b/astroid/tests/unittest_nodes.py
@@ -67,6 +67,16 @@ class AsStringTest(resources.SysPathSetup, unittest.TestCase):
node = parse(code)
self.assertEqual(node.as_string().strip(), code.strip())
+ def test_as_string_for_list_containing_uninferable(self):
+ node = test_utils.extract_node('''
+ def foo():
+ bar = [arg] * 1
+ ''')
+ binop = node.body[0].value
+ inferred = next(binop.infer())
+ self.assertEqual(inferred.as_string(), '[Uninferable]')
+ self.assertEqual(binop.as_string(), '([arg]) * (1)')
+
def test_frozenset_as_string(self):
nodes = test_utils.extract_node('''
frozenset((1, 2, 3)) #@
diff --git a/astroid/util.py b/astroid/util.py
index 9c20eb4b..6fd59cfb 100644
--- a/astroid/util.py
+++ b/astroid/util.py
@@ -76,17 +76,23 @@ class Uninferable(object):
"""Special inference object, which is returned when inference fails."""
def __repr__(self):
return 'Uninferable'
+ __str__ = __repr__
def __getattribute__(self, name):
if name == 'next':
raise AttributeError('next method should not be called')
if name.startswith('__') and name.endswith('__'):
return object.__getattribute__(self, name)
+ if name == 'accept':
+ return object.__getattribute__(self, name)
return self
def __call__(self, *args, **kwargs):
return self
+ def accept(self, visitor):
+ func = getattr(visitor, "visit_uninferable")
+ return func(self)
class BadOperationMessage(object):
"""Object which describes a TypeError occurred somewhere in the inference chain