summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2018-06-15 10:58:42 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2018-06-15 10:58:42 +0200
commit7203436c77efc2c1d363b49b5dd4542478a40d2c (patch)
tree7625d1f15d26c63538cc150d2c8dabb54bfbc56c
parent4ffa9eab67944c9caa9c6c9eac2327358fb3983f (diff)
downloadastroid-git-7203436c77efc2c1d363b49b5dd4542478a40d2c.tar.gz
Drop the requirement that lhs and rhs should have the same number of elements when inferring Starred
This improves the capabilities a bit, since we know infer those as empty lists
-rw-r--r--astroid/protocols.py19
-rw-r--r--astroid/tests/unittest_inference.py28
-rw-r--r--astroid/tests/unittest_protocols.py2
3 files changed, 38 insertions, 11 deletions
diff --git a/astroid/protocols.py b/astroid/protocols.py
index 64904524..9ebeb92a 100644
--- a/astroid/protocols.py
+++ b/astroid/protocols.py
@@ -586,18 +586,15 @@ def starred_assigned_stmts(self, node=None, context=None, asspath=None):
except exceptions.InferenceError:
yield util.Uninferable
return
- if rhs is util.Uninferable or not hasattr(rhs, 'elts'):
- # Not interested in inferred values without elts.
+ if rhs is util.Uninferable or not hasattr(rhs, 'itered'):
yield util.Uninferable
return
- elts = collections.deque(rhs.elts[:])
- if len(lhs.elts) > len(rhs.elts):
- raise exceptions.InferenceError('More targets, {targets!r}, than '
- 'values to unpack, {values!r}.',
- node=self, targets=lhs,
- values=rhs, unknown=node,
- context=context)
+ try:
+ elts = collections.deque(rhs.itered())
+ except TypeError:
+ yield util.Uninferable
+ return
# Unpack iteratively the values from the rhs of the assignment,
# until the find the starred node. What will remain will
@@ -608,11 +605,15 @@ def starred_assigned_stmts(self, node=None, context=None, asspath=None):
for index, left_node in enumerate(lhs.elts):
if not isinstance(left_node, nodes.Starred):
+ if not elts:
+ break
elts.popleft()
continue
lhs_elts = collections.deque(reversed(lhs.elts[index:]))
for right_node in lhs_elts:
if not isinstance(right_node, nodes.Starred):
+ if not elts:
+ break
elts.pop()
continue
# We're done
diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py
index 9b7c51cf..5c3800d3 100644
--- a/astroid/tests/unittest_inference.py
+++ b/astroid/tests/unittest_inference.py
@@ -4516,5 +4516,33 @@ def test_slice_inference_in_for_loops_not_working():
assert inferred == util.Uninferable
+def test_unpacking_starred_and_dicts_in_assignment():
+ node = extract_node('''
+ a, *b = {1:2, 2:3, 3:4}
+ b
+ ''')
+ inferred = next(node.infer())
+ assert isinstance(inferred, nodes.List)
+ assert inferred.as_string() == '[2, 3]'
+
+ node = extract_node('''
+ a, *b = {1:2}
+ b
+ ''')
+ inferred = next(node.infer())
+ assert isinstance(inferred, nodes.List)
+ assert inferred.as_string() == '[]'
+
+
+def test_unpacking_starred_empty_list_in_assignment():
+ node = extract_node('''
+ a, *b, c = [1, 2]
+ b #@
+ ''')
+ inferred = next(node.infer())
+ assert isinstance(inferred, nodes.List)
+ assert inferred.as_string() == '[]'
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/astroid/tests/unittest_protocols.py b/astroid/tests/unittest_protocols.py
index 6d12a001..c2619413 100644
--- a/astroid/tests/unittest_protocols.py
+++ b/astroid/tests/unittest_protocols.py
@@ -124,8 +124,6 @@ class ProtocolTests(unittest.TestCase):
def test_assign_stmts_starred_fails(self):
# Too many starred
self._helper_starred_inference_error("a, *b, *c = (1, 2, 3) #@")
- # Too many lhs values
- self._helper_starred_inference_error("a, *b, c = (1, 2) #@")
# This could be solved properly, but it complicates needlessly the
# code for assigned_stmts, without offering real benefit.
self._helper_starred_inference_error(