Skip to content

Commit b745c31

Browse files
committed
Squash one-use inference utility functions to help reduce recursion errors
1 parent 66df764 commit b745c31

File tree

4 files changed

+24
-41
lines changed

4 files changed

+24
-41
lines changed

astroid/context.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,6 @@ def clone(self):
105105
clone.extra_context = self.extra_context
106106
return clone
107107

108-
def cache_generator(self, key, generator):
109-
"""Cache result of generator into dictionary
110-
111-
Used to cache inference results"""
112-
results = []
113-
for result in generator:
114-
results.append(result)
115-
yield result
116-
117-
self.inferred[key] = tuple(results)
118-
119108
@contextlib.contextmanager
120109
def restore_path(self):
121110
path = set(self.path)

astroid/node_classes.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,19 +354,37 @@ def infer(self, context=None, **kwargs):
354354
# explicit_inference is not bound, give it self explicitly
355355
try:
356356
# pylint: disable=not-callable
357-
return self._explicit_inference(self, context, **kwargs)
357+
yield from self._explicit_inference(self, context, **kwargs)
358+
return
358359
except exceptions.UseInferenceDefault:
359360
pass
360361

361362
if not context:
362-
return self._infer(context, **kwargs)
363+
yield from self._infer(context, **kwargs)
364+
return
363365

364366
key = (self, context.lookupname, context.callcontext, context.boundnode)
365367
if key in context.inferred:
366-
return iter(context.inferred[key])
368+
yield from context.inferred[key]
369+
return
370+
371+
generator = self._infer(context, **kwargs)
372+
results = []
373+
374+
# Limit inference amount to help with performance issues with
375+
# exponentially exploding possible results.
376+
limit = MANAGER.max_inferable_values
377+
for i, result in enumerate(generator):
378+
if i >= limit:
379+
yield util.Uninferable
380+
break
381+
results.append(result)
382+
yield result
367383

368-
gen = context.cache_generator(key, self._infer(context, **kwargs))
369-
return util.limit_inference(gen, MANAGER.max_inferable_values)
384+
# Cache generated results for subsequent inferences of the
385+
# same node using the same context
386+
context.inferred[key] = tuple(results)
387+
return
370388

371389
def _repr_name(self):
372390
"""Get a name for nice representation.

astroid/util.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
88

99
import warnings
10-
from itertools import islice
1110

1211
import importlib
1312
import lazy_object_proxy
@@ -139,26 +138,3 @@ def proxy_alias(alias_name, node_type):
139138
},
140139
)
141140
return proxy(lambda: node_type)
142-
143-
144-
def limit_inference(iterator, size):
145-
"""Limit inference amount.
146-
147-
Limit inference amount to help with performance issues with
148-
exponentially exploding possible results.
149-
150-
:param iterator: Inference generator to limit
151-
:type iterator: Iterator(NodeNG)
152-
153-
:param size: Maximum mount of nodes yielded plus an
154-
Uninferable at the end if limit reached
155-
:type size: int
156-
157-
:yields: A possibly modified generator
158-
:rtype param: Iterable
159-
"""
160-
yield from islice(iterator, size)
161-
has_more = next(iterator, False)
162-
if has_more is not False:
163-
yield Uninferable
164-
return

tests/unittest_inference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ def test_del1(self):
428428
del undefined_attr
429429
"""
430430
delete = extract_node(code, __name__)
431-
self.assertRaises(InferenceError, delete.infer)
431+
self.assertRaises(InferenceError, next, delete.infer())
432432

433433
def test_del2(self):
434434
code = """

0 commit comments

Comments
 (0)