Skip to content

Commit 71f72a5

Browse files
authored
Merge pull request #84 from AlexWaygood/improve-caching
2 parents 3e99049 + 715ffb2 commit 71f72a5

File tree

2 files changed

+31
-29
lines changed

2 files changed

+31
-29
lines changed

sphinxlint/sphinxlint.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from dataclasses import dataclass
33
from os.path import splitext
44

5-
from sphinxlint.utils import hide_non_rst_blocks, po2rst
5+
from sphinxlint.utils import PER_FILE_CACHES, hide_non_rst_blocks, po2rst
66

77

88
@dataclass(frozen=True)
@@ -50,16 +50,20 @@ def check_text(filename, text, checkers, options=None):
5050

5151

5252
def check_file(filename, checkers, options: CheckersOptions = None):
53-
ext = splitext(filename)[1]
54-
if not any(ext in checker.suffixes for checker in checkers):
55-
return Counter()
5653
try:
57-
with open(filename, encoding="utf-8") as f:
58-
text = f.read()
59-
if filename.endswith(".po"):
60-
text = po2rst(text)
61-
except OSError as err:
62-
return [f"{filename}: cannot open: {err}"]
63-
except UnicodeDecodeError as err:
64-
return [f"{filename}: cannot decode as UTF-8: {err}"]
65-
return check_text(filename, text, checkers, options)
54+
ext = splitext(filename)[1]
55+
if not any(ext in checker.suffixes for checker in checkers):
56+
return Counter()
57+
try:
58+
with open(filename, encoding="utf-8") as f:
59+
text = f.read()
60+
if filename.endswith(".po"):
61+
text = po2rst(text)
62+
except OSError as err:
63+
return [f"{filename}: cannot open: {err}"]
64+
except UnicodeDecodeError as err:
65+
return [f"{filename}: cannot decode as UTF-8: {err}"]
66+
return check_text(filename, text, checkers, options)
67+
finally:
68+
for memoized_function in PER_FILE_CACHES:
69+
memoized_function.cache_clear()

sphinxlint/utils.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
from sphinxlint import rst
88

99

10+
PER_FILE_CACHES = []
11+
12+
13+
def per_file_cache(func):
14+
memoized_func = lru_cache(maxsize=None)(func)
15+
PER_FILE_CACHES.append(memoized_func)
16+
return memoized_func
17+
18+
1019
def match_size(re_match):
1120
return re_match.end() - re_match.start()
1221

@@ -29,7 +38,7 @@ def _clean_heuristic(paragraph, regex):
2938
paragraph = paragraph[: candidate.start()] + paragraph[candidate.end() :]
3039

3140

32-
@lru_cache()
41+
@per_file_cache
3342
def clean_paragraph(paragraph):
3443
"""Removes all good constructs, so detectors can focus on bad ones.
3544
@@ -45,7 +54,7 @@ def clean_paragraph(paragraph):
4554
return paragraph.replace("\x00", "\\")
4655

4756

48-
@lru_cache()
57+
@per_file_cache
4958
def escape2null(text):
5059
r"""Return a string with escape-backslashes converted to nulls.
5160
@@ -79,7 +88,7 @@ def escape2null(text):
7988
start = found + 2 # skip character after escape
8089

8190

82-
@lru_cache()
91+
@per_file_cache
8392
def paragraphs(lines):
8493
"""Yield (paragraph_line_no, paragraph_text) pairs describing
8594
paragraphs of the given lines.
@@ -150,7 +159,6 @@ def is_multiline_non_rst_block(line):
150159
return False
151160

152161

153-
_NON_RST_BLOCKS_CACHE = {}
154162
_ZERO_OR_MORE_SPACES_RE = re.compile(" *")
155163

156164

@@ -159,14 +167,7 @@ def hide_non_rst_blocks(lines, hidden_block_cb=None):
159167
160168
The filter actually replace "removed" lines by empty lines, so the
161169
line numbering still make sense.
162-
163-
This function is quite hot, so we cache the returned value where possible.
164-
The function is only "pure" when hidden_block_cb is None, however,
165-
so we can only safely cache the output when hidden_block_cb=None.
166170
"""
167-
lines = tuple(lines)
168-
if hidden_block_cb is None and lines in _NON_RST_BLOCKS_CACHE:
169-
return _NON_RST_BLOCKS_CACHE[lines]
170171
in_literal = None
171172
excluded_lines = []
172173
block_line_start = None
@@ -194,10 +195,7 @@ def hide_non_rst_blocks(lines, hidden_block_cb=None):
194195
output.append(line)
195196
if excluded_lines and hidden_block_cb:
196197
hidden_block_cb(block_line_start, "".join(excluded_lines))
197-
output = tuple(output)
198-
if hidden_block_cb is None:
199-
_NON_RST_BLOCKS_CACHE[lines] = output
200-
return output
198+
return tuple(output)
201199

202200

203201
_starts_with_directive_marker = re.compile(rf"\.\. {rst.ALL_DIRECTIVES}::").match
@@ -207,7 +205,7 @@ def hide_non_rst_blocks(lines, hidden_block_cb=None):
207205
_starts_with_substitution_definition = re.compile(r"\.\. \|[^\|]*\| ").match
208206

209207

210-
@lru_cache()
208+
@per_file_cache
211209
def type_of_explicit_markup(line):
212210
"""Tell apart various explicit markup blocks."""
213211
line = line.lstrip()

0 commit comments

Comments
 (0)