Coverage for tests/test_filter_out_literal.py: 100%
74 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-24 18:46 +0100
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-24 18:46 +0100
1from sphinxlint.utils import hide_non_rst_blocks
3LITERAL = r"""
4Hide non-RST Blocks
5===================
7This function is intended to filter out literal blocks like this one::
9 def enumerate(sequence, start=0):
10 n = start
11 for elem in sequence:
12 yield n, elem
13 n += 1
15But even if already indented it should work, see the next example.
17.. function:: hide_non_rst_blocks(stream)
19 This is an indented block, which itself contains a literal, see::
21 >>> float('+1.23')
22 1.23
24 >>> float(' -12345')
25 -12345.0
27 Yet this line should not be dropped.
29This one neither.
31.. doctest::
33 >>> # This should be dropped
34 >>> setcontext(ExtendedContext)
35"""
38LITERAL_EXPECTED = r"""
39Hide non-RST Blocks
40===================
42This function is intended to filter out literal blocks like this one::
50But even if already indented it should work, see the next example.
52.. function:: hide_non_rst_blocks(stream)
54 This is an indented block, which itself contains a literal, see::
62 Yet this line should not be dropped.
64This one neither.
66.. doctest::
70"""
73def test_filter_out_literal():
74 out = []
75 excluded = []
76 for line in hide_non_rst_blocks(
77 LITERAL.splitlines(True),
78 hidden_block_cb=lambda lineno, block: excluded.append((lineno, block)),
79 ):
80 out.append(line)
81 assert "".join(out) == LITERAL_EXPECTED
82 assert (
83 excluded[0][1]
84 == """
85 def enumerate(sequence, start=0):
86 n = start
87 for elem in sequence:
88 yield n, elem
89 n += 1
91"""
92 )
93 assert (
94 excluded[1][1]
95 == """
96 >>> float('+1.23')
97 1.23
99 >>> float(' -12345')
100 -12345.0
102"""
103 )
106LITERAL_FUNNY_INDENT = r"""
107Hide non-RST Blocks
108===================
110The case the indentation start high, still flies without really
111returning, it should still be skipped::
113 Like we start at 4...
115 Does not mean we'll keep at 4...
117 Maybe we get down at 1
118 ======================
120 Because why not, at long as we don't get back to the indentation of
121 the initial line with the `::`.
123But now we're really back out of the block.
124"""
127LITERAL_FUNNY_INDENT_EXPECTED = r"""
128Hide non-RST Blocks
129===================
131The case the indentation start high, still flies without really
132returning, it should still be skipped::
144But now we're really back out of the block.
145"""
148def test_filter_out_funny_indent():
149 out = []
150 excluded = []
151 for line in hide_non_rst_blocks(
152 LITERAL_FUNNY_INDENT.splitlines(True),
153 hidden_block_cb=lambda lineno, block: excluded.append((lineno, block)),
154 ):
155 out.append(line)
156 assert "".join(out) == LITERAL_FUNNY_INDENT_EXPECTED
157 assert (
158 excluded[0][1]
159 == """
160 Like we start at 4...
162 Does not mean we'll keep at 4...
164 Maybe we get down at 1
165 ======================
167 Because why not, at long as we don't get back to the indentation of
168 the initial line with the `::`.
170"""
171 )
174CODE_BLOCK = """
175The code blocks should also be removed, like:
177.. code-block:: shell-session
179 $ cat multiple_line_file
180 Even if there's empty lines
182 in the code block.
184But not this one.
185"""
186CODE_BLOCK_EXPECTED = """
187The code blocks should also be removed, like:
189.. code-block:: shell-session
196But not this one.
197"""
200def test_filter_out_code_block():
201 out = []
202 excluded = []
203 for line in hide_non_rst_blocks(
204 CODE_BLOCK.splitlines(True),
205 hidden_block_cb=lambda lineno, block: excluded.append((lineno, block)),
206 ):
207 out.append(line)
208 assert "".join(out) == CODE_BLOCK_EXPECTED
209 assert (
210 excluded[0][1]
211 == """
212 $ cat multiple_line_file
213 Even if there's empty lines
215 in the code block.
217"""
218 )
221PRODUCTIONLIST_BLOCK = """
222The grammar for a replacement field is as follows:
224 .. productionlist:: format-string
225 replacement_field: "{" [`field_name`] ["!" `conversion`] [":" `format_spec`] "}"
226 field_name: arg_name ("." `attribute_name` | "[" `element_index` "]")*
227 arg_name: [`identifier` | `digit`+]
228 attribute_name: `identifier`
229 element_index: `digit`+ | `index_string`
230 index_string: <any source character except "]"> +
231 conversion: "r" | "s" | "a"
232 format_spec: <described in the next section>
234In less formal terms, the replacement field can start with a *field_name* that specifies
235the object whose value is to be formatted and inserted
236into the output instead of the replacement field.
237"""
238PRODUCTIONLIST_BLOCK_EXPECTED = """
239The grammar for a replacement field is as follows:
241 .. productionlist:: format-string
251In less formal terms, the replacement field can start with a *field_name* that specifies
252the object whose value is to be formatted and inserted
253into the output instead of the replacement field.
254"""
257def test_filter_out_production_list():
258 out = []
259 for line in hide_non_rst_blocks(PRODUCTIONLIST_BLOCK.splitlines(True)):
260 out.append(line)
261 assert "".join(out) == PRODUCTIONLIST_BLOCK_EXPECTED
264KEEP_THAT = """
265The simpler part of :pep:`328` was implemented in Python 2.4: parentheses could now
266be used to enclose the names imported from a module using the ``from ... import
267...`` statement, making it easier to import many different names.
268"""
270KEEP_THAT_EXPECTED = """
271The simpler part of :pep:`328` was implemented in Python 2.4: parentheses could now
272be used to enclose the names imported from a module using the ``from ... import
273...`` statement, making it easier to import many different names.
274"""
277def test_filter_out_dont_filter_out_unwanted_things():
278 out = []
279 for line in hide_non_rst_blocks(KEEP_THAT.splitlines(True)):
280 out.append(line)
281 assert "".join(out) == KEEP_THAT_EXPECTED
284CONSECUTIVE_PRODUCTION_LIST = """
285.. productionlist:: python-grammar
286 del_stmt: "del" `target_list`
288.. productionlist:: python-grammar
289 del_stmt: "del" `target_list`
290"""
292CONSECUTIVE_PRODUCTION_LIST_EXPECTED = """
293.. productionlist:: python-grammar
296.. productionlist:: python-grammar
298"""
301def test_consecutive_production_list():
302 out = []
303 for line in hide_non_rst_blocks(CONSECUTIVE_PRODUCTION_LIST.splitlines(True)):
304 out.append(line)
305 assert "".join(out) == CONSECUTIVE_PRODUCTION_LIST_EXPECTED
308ATTENTION = """
309This is a test for an attention admonition.
311.. attention::
312 An admonition can contain RST so it should **NOT** be dropped.
314and that's it.
315"""
318def test_filter_out_attention():
319 out = []
320 excluded = []
321 for line in hide_non_rst_blocks(
322 ATTENTION.splitlines(True),
323 hidden_block_cb=lambda lineno, block: excluded.append((lineno, block)),
324 ):
325 out.append(line)
326 assert "".join(out) == ATTENTION
327 assert not excluded
330NOTE = """
331This is a note, it contains rst, so it should **not** be dropped:
333.. note::
335 hello I am a not **I can** contain rst.
337End of it.
338"""
341def test_filter_out_note():
342 out = []
343 excluded = []
344 for line in hide_non_rst_blocks(
345 NOTE.splitlines(True),
346 hidden_block_cb=lambda lineno, block: excluded.append((lineno, block)),
347 ):
348 out.append(line)
349 assert "".join(out) == NOTE
350 assert not excluded
353UNKNOWN = """
354This is an unknown directive, to avoid false positives, just drop its content.
356.. this_is_not_a_known_directive::
358 So this can contain rst, or arbitary text.
360In the face of ambiguity, refuse the temptation to guess.
361"""
363UNKNOWN_EXPECTED = """
364This is an unknown directive, to avoid false positives, just drop its content.
370In the face of ambiguity, refuse the temptation to guess.
371"""
374def test_filter_out_unknown():
375 out = []
376 excluded = []
377 for line in hide_non_rst_blocks(
378 UNKNOWN.splitlines(True),
379 hidden_block_cb=lambda lineno, block: excluded.append((lineno, block)),
380 ):
381 out.append(line)
382 assert "".join(out) == UNKNOWN_EXPECTED