summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--astroid/protocols.py38
-rw-r--r--astroid/tests/unittest_inference.py14
3 files changed, 43 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 722d4284..ac4a38b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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()