11"""Just a bunch of utility functions for sphinxlint."""
2+ from functools import lru_cache
3+
24import regex as re
35from polib import pofile
46
@@ -27,6 +29,7 @@ def _clean_heuristic(paragraph, regex):
2729 paragraph = paragraph [: candidate .start ()] + paragraph [candidate .end () :]
2830
2931
32+ @lru_cache ()
3033def clean_paragraph (paragraph ):
3134 """Removes all good constructs, so detectors can focus on bad ones.
3235
@@ -42,6 +45,7 @@ def clean_paragraph(paragraph):
4245 return paragraph .replace ("\x00 " , "\\ " )
4346
4447
48+ @lru_cache ()
4549def escape2null (text ):
4650 r"""Return a string with escape-backslashes converted to nulls.
4751
@@ -75,10 +79,12 @@ def escape2null(text):
7579 start = found + 2 # skip character after escape
7680
7781
82+ @lru_cache ()
7883def paragraphs (lines ):
7984 """Yield (paragraph_line_no, paragraph_text) pairs describing
8085 paragraphs of the given lines.
8186 """
87+ output = []
8288 paragraph = []
8389 paragraph_lno = 1
8490 for lno , line in enumerate (lines , start = 1 ):
@@ -88,10 +94,11 @@ def paragraphs(lines):
8894 paragraph_lno = lno
8995 paragraph .append (line )
9096 elif paragraph :
91- yield paragraph_lno , "" .join (paragraph )
97+ output . append (( paragraph_lno , "" .join (paragraph )) )
9298 paragraph = []
9399 if paragraph :
94- yield paragraph_lno , "" .join (paragraph )
100+ output .append ((paragraph_lno , "" .join (paragraph )))
101+ return tuple (output )
95102
96103
97104def looks_like_glued (match ):
@@ -143,12 +150,22 @@ def is_multiline_non_rst_block(line):
143150 return False
144151
145152
153+ _NON_RST_BLOCKS_CACHE = {}
154+
155+
146156def hide_non_rst_blocks (lines , hidden_block_cb = None ):
147157 """Filters out literal, comments, code blocks, ...
148158
149159 The filter actually replace "removed" lines by empty lines, so the
150160 line numbering still make sense.
161+
162+ This function is quite hot, so we cache the returned value where possible.
163+ The function is only "pure" when hidden_block_cb is None, however,
164+ so we can only safely cache the output when hidden_block_cb=None.
151165 """
166+ lines = tuple (lines )
167+ if hidden_block_cb is None and lines in _NON_RST_BLOCKS_CACHE :
168+ return _NON_RST_BLOCKS_CACHE [lines ]
152169 in_literal = None
153170 excluded_lines = []
154171 block_line_start = None
@@ -176,9 +193,13 @@ def hide_non_rst_blocks(lines, hidden_block_cb=None):
176193 output .append (line )
177194 if excluded_lines and hidden_block_cb :
178195 hidden_block_cb (block_line_start , "" .join (excluded_lines ))
196+ output = tuple (output )
197+ if hidden_block_cb is None :
198+ _NON_RST_BLOCKS_CACHE [lines ] = output
179199 return output
180200
181201
202+ @lru_cache ()
182203def type_of_explicit_markup (line ):
183204 """Tell apart various explicit markup blocks."""
184205 line = line .lstrip ()
0 commit comments