diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2018-06-15 10:58:42 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-06-15 10:58:42 +0200 |
commit | 7203436c77efc2c1d363b49b5dd4542478a40d2c (patch) | |
tree | 7625d1f15d26c63538cc150d2c8dabb54bfbc56c | |
parent | 4ffa9eab67944c9caa9c6c9eac2327358fb3983f (diff) | |
download | astroid-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.py | 19 | ||||
-rw-r--r-- | astroid/tests/unittest_inference.py | 28 | ||||
-rw-r--r-- | astroid/tests/unittest_protocols.py | 2 |
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( |