summaryrefslogtreecommitdiff
path: root/astroid/inference.py
diff options
context:
space:
mode:
authorBryce Guinta <bryce.paul.guinta@gmail.com>2018-01-20 10:10:29 -0700
committerBryce Guinta <bryce.paul.guinta@gmail.com>2018-03-02 21:59:08 -0700
commitb604b267f4876298d142f165713d6be1bd77790e (patch)
tree1d396f094a4c4bd05e02eaa23cb38dd72b7de800 /astroid/inference.py
parent9b5aa979effadfe55be602f7e157368316a373be (diff)
downloadastroid-git-b604b267f4876298d142f165713d6be1bd77790e.tar.gz
Fix duplicate values in inferred dictionary node from dictionary unpacking
Diffstat (limited to 'astroid/inference.py')
-rw-r--r--astroid/inference.py28
1 files changed, 26 insertions, 2 deletions
diff --git a/astroid/inference.py b/astroid/inference.py
index 5c83ed5e..37b1b2bb 100644
--- a/astroid/inference.py
+++ b/astroid/inference.py
@@ -89,6 +89,29 @@ def infer_map(self, context=None):
yield new_seq
+def _update_with_replacement(lhs_dict, rhs_dict):
+ """Delete nodes that equate to duplicate keys
+
+ Since an astroid node doesn't 'equal' another node with the same value,
+ this function uses the as_string method to make sure duplicate keys
+ don't get through
+
+ Note that both the key and the value are astroid nodes
+
+ Fixes issue with DictUnpack causing duplicte keys
+ in inferred Dict items
+
+ :param dict(nodes.NodeNG, nodes.NodeNG) lhs_dict: Dictionary to 'merge' nodes into
+ :param dict(nodes.NodeNG, nodes.NodeNG) rhs_dict: Dictionary with nodes to pull from
+ :return dict(nodes.NodeNG, nodes.NodeNG): merged dictionary of nodes
+ """
+ combined_dict = itertools.chain(lhs_dict.items(), rhs_dict.items())
+ # Overwrite keys which have the same string values
+ string_map = {key.as_string(): (key, value) for key, value in combined_dict}
+ # Return to dictionary
+ return dict(string_map.values())
+
+
def _infer_map(node, context):
"""Infer all values based on Dict.items"""
values = {}
@@ -100,14 +123,15 @@ def _infer_map(node, context):
if not isinstance(double_starred, nodes.Dict):
raise exceptions.InferenceError(node=node,
context=context)
- values.update(_infer_map(double_starred, context))
+ unpack_items = _infer_map(double_starred, context)
+ values = _update_with_replacement(values, unpack_items)
else:
key = helpers.safe_infer(name, context=context)
value = helpers.safe_infer(value, context=context)
if any(elem in (None, util.Uninferable) for elem in (key, value)):
raise exceptions.InferenceError(node=node,
context=context)
- values[key] = value
+ values = _update_with_replacement(values, {key: value})
return values