Skip to content

Commit 87a9653

Browse files
Fix Use of cache on methods can lead to memory leaks
1 parent 65a4360 commit 87a9653

File tree

3 files changed

+11
-17
lines changed

3 files changed

+11
-17
lines changed

astroid/interpreter/objectmodel.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
import os
2626
import pprint
2727
import types
28-
from functools import lru_cache
29-
from typing import TYPE_CHECKING, Optional
28+
from typing import TYPE_CHECKING, List, Optional
3029

3130
import astroid
3231
from astroid import util
@@ -41,6 +40,7 @@
4140
from astroid.objects import Property
4241

4342
IMPL_PREFIX = "attr_"
43+
LEN_OF_IMPL_PREFIX = len(IMPL_PREFIX)
4444

4545

4646
def _dunder_dict(instance, attributes):
@@ -100,20 +100,16 @@ def __get__(self, instance, cls=None):
100100
def __contains__(self, name):
101101
return name in self.attributes()
102102

103-
@lru_cache(maxsize=None)
104-
def attributes(self):
103+
def attributes(self) -> List[str]:
105104
"""Get the attributes which are exported by this object model."""
106-
return [
107-
obj[len(IMPL_PREFIX) :] for obj in dir(self) if obj.startswith(IMPL_PREFIX)
108-
]
105+
return [o[LEN_OF_IMPL_PREFIX:] for o in dir(self) if o.startswith(IMPL_PREFIX)]
109106

110107
def lookup(self, name):
111108
"""Look up the given *name* in the current model
112109
113110
It should return an AST or an interpreter object,
114111
but if the name is not found, then an AttributeInferenceError will be raised.
115112
"""
116-
117113
if name in self.attributes():
118114
return getattr(self, IMPL_PREFIX + name)
119115
raise AttributeInferenceError(target=self._instance, attribute=name)

astroid/nodes/node_classes.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,21 +367,19 @@ def get_children(self):
367367
class LookupMixIn:
368368
"""Mixin to look up a name in the right scope."""
369369

370-
@lru_cache(maxsize=None)
371-
def lookup(self, name):
370+
@lru_cache(maxsize=None) # pylint: disable=cache-max-size-none # noqa
371+
def lookup(self, name: str) -> typing.Tuple[str, typing.List[NodeNG]]:
372372
"""Lookup where the given variable is assigned.
373373
374374
The lookup starts from self's scope. If self is not a frame itself
375375
and the name is found in the inner frame locals, statements will be
376376
filtered to remove ignorable statements according to self's location.
377377
378378
:param name: The name of the variable to find assignments for.
379-
:type name: str
380379
381380
:returns: The scope node and the list of assignments associated to the
382381
given name according to the scope where it has been found (locals,
383382
globals or builtin).
384-
:rtype: tuple(str, list(NodeNG))
385383
"""
386384
return self.scope().scope_lookup(self, name)
387385

astroid/transforms.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
44

55
import collections
6-
from functools import lru_cache
6+
from typing import TYPE_CHECKING
77

88
from astroid.context import _invalidate_cache
99

10+
if TYPE_CHECKING:
11+
from astroid import NodeNG
12+
1013

1114
class TransformVisitor:
1215
"""A visitor for handling transforms.
@@ -17,13 +20,10 @@ class TransformVisitor:
1720
transforms for each encountered node.
1821
"""
1922

20-
TRANSFORM_MAX_CACHE_SIZE = 10000
21-
2223
def __init__(self):
2324
self.transforms = collections.defaultdict(list)
2425

25-
@lru_cache(maxsize=TRANSFORM_MAX_CACHE_SIZE)
26-
def _transform(self, node):
26+
def _transform(self, node: "NodeNG") -> "NodeNG":
2727
"""Call matching transforms for the given node if any and return the
2828
transformed node.
2929
"""

0 commit comments

Comments
 (0)