Coverage for tests/test_filter_out_literal.py: 100%

1 from sphinxlint.utils import hide_non_rst_blocks

2

3 LITERAL = r"""

4 Hide non-RST Blocks

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

6

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

15 But 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

29 This one neither.

30

31.. doctest::

32

33 >>> # This should be dropped

34 >>> setcontext(ExtendedContext)

35"""

36

37

38 LITERAL_EXPECTED = r"""

39 Hide non-RST Blocks

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

41

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

43

44

45

46

47

48

49

50 But 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

64 This one neither.

65

66.. doctest::

67

68

69

70"""

71

72

73 def 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

106 LITERAL_FUNNY_INDENT = r"""

107 Hide non-RST Blocks

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

109

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

111 returning, 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

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

124"""

125

126

127 LITERAL_FUNNY_INDENT_EXPECTED = r"""

128 Hide non-RST Blocks

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

130

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

132 returning, it should still be skipped::

133

134

135

136

137

138

139

140

141

142

143

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

145"""

146

147

148 def 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

174 CODE_BLOCK = """

175 The 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

184 But not this one.

185"""

186 CODE_BLOCK_EXPECTED = """

187 The code blocks should also be removed, like:

188

189.. code-block:: shell-session

190

191

192

193

194

195

196 But not this one.

197"""

198

199

200 def 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

221 PRODUCTIONLIST_BLOCK = """

222 The 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

234 In less formal terms, the replacement field can start with a *field_name* that specifies

235 the object whose value is to be formatted and inserted

236 into the output instead of the replacement field.

237"""

238 PRODUCTIONLIST_BLOCK_EXPECTED = """

239 The grammar for a replacement field is as follows:

240

241 .. productionlist:: format-string

242

243

244

245

246

247

248

249

250

251 In less formal terms, the replacement field can start with a *field_name* that specifies

252 the object whose value is to be formatted and inserted

253 into the output instead of the replacement field.

254"""

255

256

257 def 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

264 KEEP_THAT = """

265 The simpler part of :pep:`328` was implemented in Python 2.4: parentheses could now

266 be 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

270 KEEP_THAT_EXPECTED = """

271 The simpler part of :pep:`328` was implemented in Python 2.4: parentheses could now

272 be 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

277 def 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

284 CONSECUTIVE_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

292 CONSECUTIVE_PRODUCTION_LIST_EXPECTED = """

293.. productionlist:: python-grammar

294

295

296.. productionlist:: python-grammar

297

298"""

299

300

301 def 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

308 ATTENTION = """

309 This is a test for an attention admonition.

310

311.. attention::

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

313

314 and that's it.

315"""

316

317

318 def 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

330 NOTE = """

331 This 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

337 End of it.

338"""

339

340

341 def 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

353 UNKNOWN = """

354 This 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

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

361"""

362

363 UNKNOWN_EXPECTED = """

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

365

366

367

368

369

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

371"""

372

373

374 def 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