Skip to content

Remove inference tip cache #1832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion astroid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
UnresolvableName,
UseInferenceDefault,
)
from astroid.inference_tip import _inference_tip_cached, inference_tip
from astroid.inference_tip import inference_tip
from astroid.objects import ExceptionInstance

# isort: off
Expand Down
26 changes: 5 additions & 21 deletions astroid/inference_tip.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,22 @@
import wrapt

from astroid import bases, util
from astroid.exceptions import InferenceOverwriteError, UseInferenceDefault
from astroid.exceptions import InferenceOverwriteError
from astroid.nodes import NodeNG
from astroid.typing import InferFn

InferOptions = typing.Union[
NodeNG, bases.Instance, bases.UnboundMethod, typing.Type[util.Uninferable]
]

_cache: dict[tuple[InferFn, NodeNG], list[InferOptions] | None] = {}


def clear_inference_tip_cache() -> None:
"""Clear the inference tips cache."""
_cache.clear()


@wrapt.decorator
def _inference_tip_cached(
def _inference_tip(
func: InferFn, instance: None, args: typing.Any, kwargs: typing.Any
) -> Iterator[InferOptions]:
"""Cache decorator used for inference tips"""
node = args[0]
try:
result = _cache[func, node]
# If through recursion we end up trying to infer the same
# func + node we raise here.
if result is None:
raise UseInferenceDefault()
except KeyError:
_cache[func, node] = None
result = _cache[func, node] = list(func(*args, **kwargs))
assert result
result = list(func(*args, **kwargs))
assert result
return iter(result)


Expand Down Expand Up @@ -84,7 +68,7 @@ def transform(node: NodeNG, infer_function: InferFn = infer_function) -> NodeNG:
)
)
# pylint: disable=no-value-for-parameter
node._explicit_inference = _inference_tip_cached(infer_function)
node._explicit_inference = _inference_tip(infer_function)
return node

return transform
3 changes: 0 additions & 3 deletions astroid/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,9 @@ def clear_cache(self) -> None:
re-register transforms."""
# import here because of cyclic imports
# pylint: disable=import-outside-toplevel
from astroid.inference_tip import clear_inference_tip_cache
from astroid.interpreter.objectmodel import ObjectModel
from astroid.nodes.node_classes import LookupMixIn

clear_inference_tip_cache()

self.astroid_cache.clear()
# NB: not a new TransformVisitor()
AstroidManager.brain["_transform"].transforms = collections.defaultdict(list)
Expand Down
24 changes: 24 additions & 0 deletions tests/unittest_regrtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,30 @@ def d(self):
assert isinstance(inferred, Instance)
assert inferred.qname() == ".A"

def test_inference_context_consideration(self) -> None:
# Test for https://github.com/PyCQA/astroid/issues/1828
code = """
class Base:
def return_type(self):
return type(self)()

class A(Base):
def method(self):
return self.return_type()

class B(Base):
def method(self):
return self.return_type()

A().method() #@
B().method() #@
"""
node1, node2 = extract_node(code)
inferred1 = next(node1.infer())
assert inferred1.qname() == ".A"
inferred2 = next(node2.infer())
assert inferred2.qname() == ".B"


class Whatever:
a = property(lambda x: x, lambda x: x) # type: ignore[misc]
Expand Down
4 changes: 1 addition & 3 deletions tests/unittest_scoped_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1699,9 +1699,7 @@ def __init__(self):
"FinalClass",
"ClassB",
"MixinB",
# We don't recognize what 'cls' is at time of .format() call, only
# what it is at the end.
# "strMixin",
"strMixin",
"ClassA",
"MixinA",
"intMixin",
Expand Down