diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2018-06-14 09:14:56 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-06-14 09:14:56 +0200 |
commit | d68a8cabc071c44608a97d08ff736ccfea96711d (patch) | |
tree | 2b83e61680c6e02ed4871bfc8bbcf891d5a2ef6c | |
parent | 7e0c84151781dc4879a4d8807837a8b9be03549d (diff) | |
download | astroid-git-d68a8cabc071c44608a97d08ff736ccfea96711d.tar.gz |
Support unpacking for dicts in assignments
Close #268
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | astroid/protocols.py | 38 | ||||
-rw-r--r-- | astroid/tests/unittest_inference.py | 14 |
3 files changed, 43 insertions, 13 deletions
@@ -7,6 +7,10 @@ What's New in astroid 2.0? Release Date: Unknown + * Support unpacking for dicts in assignments + + Close #268 + * Add support for inferring functools.partial Close #125 diff --git a/astroid/protocols.py b/astroid/protocols.py index 2d72ec82..08d3b7a4 100644 --- a/astroid/protocols.py +++ b/astroid/protocols.py @@ -373,7 +373,15 @@ def _resolve_asspart(parts, asspath, context): asspath = asspath[:] index = asspath.pop(0) for part in parts: - if hasattr(part, 'getitem'): + assigned = None + if isinstance(part, nodes.Dict): + # A dictionary in an iterating context + try: + assigned, _ = part.items[index] + except KeyError: + return + + elif hasattr(part, 'getitem'): index_node = nodes.Const(index) try: assigned = part.getitem(index_node, context) @@ -381,19 +389,23 @@ def _resolve_asspart(parts, asspath, context): # unexpected exception ? except (exceptions.AstroidTypeError, exceptions.AstroidIndexError): return - if not asspath: - # we achieved to resolved the assignment path, don't infer the - # last part - yield assigned - elif assigned is util.Uninferable: + + if not assigned: + return + + if not asspath: + # we achieved to resolved the assignment path, don't infer the + # last part + yield assigned + elif assigned is util.Uninferable: + return + else: + # we are not yet on the last part of the path search on each + # possibly inferred value + try: + yield from _resolve_asspart(assigned.infer(context), asspath, context) + except exceptions.InferenceError: return - else: - # we are not yet on the last part of the path search on each - # possibly inferred value - try: - yield from _resolve_asspart(assigned.infer(context), asspath, context) - except exceptions.InferenceError: - return @decorators.raise_if_nothing_inferred diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py index 0d41c2e7..099966bc 100644 --- a/astroid/tests/unittest_inference.py +++ b/astroid/tests/unittest_inference.py @@ -4461,5 +4461,19 @@ def test_cannot_infer_call_result_for_builtin_methods(): next(lenmeth.infer_call_result(None, None)) +def test_unpack_dicts_in_assignment(): + ast_nodes = extract_node(''' + a, b = {1:2, 2:3} + a #@ + b #@ + ''') + first_inferred = next(ast_nodes[0].infer()) + second_inferred = next(ast_nodes[1].infer()) + assert isinstance(first_inferred, nodes.Const) + assert first_inferred.value == 1 + assert isinstance(second_inferred, nodes.Const) + assert second_inferred.value == 2 + + if __name__ == '__main__': unittest.main() |