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

1from sphinxlint.utils import hide_non_rst_blocks 

2 

3LITERAL = r""" 

4Hide non-RST Blocks 

5=================== 

6 

7This function is intended to filter out literal blocks like this one:: 

8 

9 def enumerate(sequence, start=0): 

10 n = start 

11 for elem in sequence: 

12 yield n, elem 

13 n += 1 

14 

15But even if already indented it should work, see the next example. 

16 

17.. function:: hide_non_rst_blocks(stream) 

18 

19 This is an indented block, which itself contains a literal, see:: 

20 

21 >>> float('+1.23') 

22 1.23 

23 

24 >>> float(' -12345') 

25 -12345.0 

26 

27 Yet this line should not be dropped. 

28 

29This one neither. 

30 

31.. doctest:: 

32 

33 >>> # This should be dropped 

34 >>> setcontext(ExtendedContext) 

35""" 

36 

37 

38LITERAL_EXPECTED = r""" 

39Hide non-RST Blocks 

40=================== 

41 

42This function is intended to filter out literal blocks like this one:: 

43 

44 

45 

46 

47 

48 

49 

50But even if already indented it should work, see the next example. 

51 

52.. function:: hide_non_rst_blocks(stream) 

53 

54 This is an indented block, which itself contains a literal, see:: 

55 

56 

57 

58 

59 

60 

61 

62 Yet this line should not be dropped. 

63 

64This one neither. 

65 

66.. doctest:: 

67 

68 

69 

70""" 

71 

72 

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 

90 

91""" 

92 ) 

93 assert ( 

94 excluded[1][1] 

95 == """ 

96 >>> float('+1.23') 

97 1.23 

98 

99 >>> float(' -12345') 

100 -12345.0 

101 

102""" 

103 ) 

104 

105 

106LITERAL_FUNNY_INDENT = r""" 

107Hide non-RST Blocks 

108=================== 

109 

110The case the indentation start high, still flies without really 

111returning, it should still be skipped:: 

112 

113 Like we start at 4... 

114 

115 Does not mean we'll keep at 4... 

116 

117 Maybe we get down at 1 

118 ====================== 

119 

120 Because why not, at long as we don't get back to the indentation of 

121 the initial line with the `::`. 

122 

123But now we're really back out of the block. 

124""" 

125 

126 

127LITERAL_FUNNY_INDENT_EXPECTED = r""" 

128Hide non-RST Blocks 

129=================== 

130 

131The case the indentation start high, still flies without really 

132returning, it should still be skipped:: 

133 

134 

135 

136 

137 

138 

139 

140 

141 

142 

143 

144But now we're really back out of the block. 

145""" 

146 

147 

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... 

161 

162 Does not mean we'll keep at 4... 

163 

164 Maybe we get down at 1 

165 ====================== 

166 

167 Because why not, at long as we don't get back to the indentation of 

168 the initial line with the `::`. 

169 

170""" 

171 ) 

172 

173 

174CODE_BLOCK = """ 

175The code blocks should also be removed, like: 

176 

177.. code-block:: shell-session 

178 

179 $ cat multiple_line_file 

180 Even if there's empty lines 

181 

182 in the code block. 

183 

184But not this one. 

185""" 

186CODE_BLOCK_EXPECTED = """ 

187The code blocks should also be removed, like: 

188 

189.. code-block:: shell-session 

190 

191 

192 

193 

194 

195 

196But not this one. 

197""" 

198 

199 

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 

214 

215 in the code block. 

216 

217""" 

218 ) 

219 

220 

221PRODUCTIONLIST_BLOCK = """ 

222The grammar for a replacement field is as follows: 

223 

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> 

233 

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: 

240 

241 .. productionlist:: format-string 

242 

243 

244 

245 

246 

247 

248 

249 

250 

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""" 

255 

256 

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 

262 

263 

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""" 

269 

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""" 

275 

276 

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 

282 

283 

284CONSECUTIVE_PRODUCTION_LIST = """ 

285.. productionlist:: python-grammar 

286 del_stmt: "del" `target_list` 

287 

288.. productionlist:: python-grammar 

289 del_stmt: "del" `target_list` 

290""" 

291 

292CONSECUTIVE_PRODUCTION_LIST_EXPECTED = """ 

293.. productionlist:: python-grammar 

294 

295 

296.. productionlist:: python-grammar 

297 

298""" 

299 

300 

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 

306 

307 

308ATTENTION = """ 

309This is a test for an attention admonition. 

310 

311.. attention:: 

312 An admonition can contain RST so it should **NOT** be dropped. 

313 

314and that's it. 

315""" 

316 

317 

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 

328 

329 

330NOTE = """ 

331This is a note, it contains rst, so it should **not** be dropped: 

332 

333.. note:: 

334 

335 hello I am a not **I can** contain rst. 

336 

337End of it. 

338""" 

339 

340 

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 

351 

352 

353UNKNOWN = """ 

354This is an unknown directive, to avoid false positives, just drop its content. 

355 

356.. this_is_not_a_known_directive:: 

357 

358 So this can contain rst, or arbitary text. 

359 

360In the face of ambiguity, refuse the temptation to guess. 

361""" 

362 

363UNKNOWN_EXPECTED = """ 

364This is an unknown directive, to avoid false positives, just drop its content. 

365 

366 

367 

368 

369 

370In the face of ambiguity, refuse the temptation to guess. 

371""" 

372 

373 

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