diff options
author | Bryce Guinta <bryce.paul.guinta@gmail.com> | 2018-01-27 18:15:00 -0700 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-01-28 16:26:10 +0100 |
commit | 53ab62402b2842dbe79cfbd91f3d698d74200485 (patch) | |
tree | ac2821e2d3e00db4fdf1dec04947f19c60210907 /astroid/context.py | |
parent | f8b7af62086478129bc9565696f5c60e69ae5508 (diff) | |
download | astroid-git-53ab62402b2842dbe79cfbd91f3d698d74200485.tar.gz |
Fix inference issue with inference path cloning
Copy inference path in inference context upon cloning to prevent diverging inference paths causing uninferable results
Diffstat (limited to 'astroid/context.py')
-rw-r--r-- | astroid/context.py | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/astroid/context.py b/astroid/context.py index 627bae5d..838e2813 100644 --- a/astroid/context.py +++ b/astroid/context.py @@ -7,20 +7,43 @@ """Various context related utilities, including inference and call contexts.""" import contextlib +import copy import pprint class InferenceContext(object): + """Provide context for inference + + Store already inferred nodes to save time + Account for already visited nodes to infinite stop infinite recursion + """ + __slots__ = ('path', 'lookupname', 'callcontext', 'boundnode', 'inferred') def __init__(self, path=None, inferred=None): self.path = path or set() + """Path of visited nodes and their lookupname + :type: set(tuple(NodeNG, optional(str)))""" self.lookupname = None self.callcontext = None self.boundnode = None self.inferred = inferred or {} + """ + :type: dict(seq, seq) + + Inferred node contexts to their mapped results + Currently the key is (node, lookupname, callcontext, boundnode) + and the value is tuple of the inferred results + """ def push(self, node): + """Push node into inference path + + :return: True if node is already in context path else False + :rtype: bool + + Allows one to see if the given node has already + been looked at for this inference context""" name = self.lookupname if (node, name) in self.path: return True @@ -29,13 +52,21 @@ class InferenceContext(object): return False def clone(self): + """Clone inference path + + For example, each side of a binary operation (BinOp) + starts with the same context but diverge as each side is inferred + so the InferenceContext will need be cloned""" # XXX copy lookupname/callcontext ? - clone = InferenceContext(self.path, inferred=self.inferred) + clone = InferenceContext(copy.copy(self.path), inferred=self.inferred) clone.callcontext = self.callcontext clone.boundnode = self.boundnode return clone def cache_generator(self, key, generator): + """Cache result of generator into dictionary + + Used to cache inference results""" results = [] for result in generator: results.append(result) |