Skip to content

Commit d89a59e

Browse files
authored
Address a potential memory leak when storing hooks instances (#66)
From Ruff: > Using the functools.lru_cache and functools.cache decorators on methods can lead to memory leaks, as the global cache will retain a reference to the instance, preventing it from being garbage collected.
1 parent 9338ca0 commit d89a59e

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

properdocs/config/config_options.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import functools
4+
import importlib.util
45
import ipaddress
56
import logging
67
import os
@@ -1172,6 +1173,7 @@ def __init__(self, plugins_key: str) -> None:
11721173
super().__init__()
11731174
self.default = []
11741175
self.plugins_key = plugins_key
1176+
self._loaded_hooks: dict[tuple[str, str], types.ModuleType] = {}
11751177

11761178
def pre_validation(self, config: Config, key_name: str):
11771179
self._base_option = ListOfItems(File(exists=True))
@@ -1183,13 +1185,13 @@ def run_validation(self, value: object) -> Mapping[str, Any]:
11831185
assert isinstance(value, list)
11841186

11851187
hooks = {}
1186-
for name, path in zip(value, paths):
1188+
for name, path in zip(value, paths, strict=True):
11871189
hooks[name] = self._load_hook(name, path)
11881190
return hooks
11891191

1190-
@functools.cache
1191-
def _load_hook(self, name, path):
1192-
import importlib.util
1192+
def _load_hook(self, name: str, path: str) -> types.ModuleType:
1193+
if loaded_hook := self._loaded_hooks.get((name, path)):
1194+
return loaded_hook
11931195

11941196
spec = importlib.util.spec_from_file_location(name, path)
11951197
if spec is None:
@@ -1206,6 +1208,7 @@ def _load_hook(self, name, path):
12061208
finally:
12071209
sys.path[:] = old_sys_path
12081210

1211+
self._loaded_hooks[name, path] = module
12091212
return module
12101213

12111214
def post_validation(self, config: Config, key_name: str):

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ select = [
180180
"F", "E", "W", "I", "UP", "YTT", "ASYNC", "C4", "DTZ", "T10", "FA", "ISC", "PIE", "T20", "RSE",
181181
"N803", "N804", "N805", "N806", "N807", "N815", "N999",
182182
"S201", "S202", "S303", "S304", "S305", "S306", "S602", "S604", "S605", "S612",
183-
"B002", "B003", "B004", "B005", "B008", "B009", "B010", "B011", "B012", "B013", "B014", "B015", "B016", "B017", "B018", "B020", "B021", "B022", "B023", "B025", "B026", "B029", "B030", "B031", "B032", "B033", "B034", "B035", "B039", "B909",
183+
"B002", "B003", "B004", "B005", "B008", "B009", "B010", "B011", "B012", "B013", "B014", "B015", "B016", "B017", "B018", "B019", "B020", "B021", "B022", "B023", "B025", "B026", "B029", "B030", "B031", "B032", "B033", "B034", "B035", "B039", "B909",
184184
"COM818",
185185
"D200", "D201", "D202", "D204", "D207", "D208", "D209", "D210", "D211", "D213", "D214", "D300", "D301", "D400", "D402", "D403", "D405", "D412", "D414", "D415", "D416", "D417", "D419",
186186
"LOG001", "LOG007", "LOG009", "LOG015",

0 commit comments

Comments
 (0)