Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/botocore/docs/bcdoc/style.py: 27%

313 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:51 +0000

1# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"). You 

4# may not use this file except in compliance with the License. A copy of 

5# the License is located at 

6# 

7# http://aws.amazon.com/apache2.0/ 

8# 

9# or in the "license" file accompanying this file. This file is 

10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 

11# ANY KIND, either express or implied. See the License for the specific 

12# language governing permissions and limitations under the License. 

13 

14import logging 

15 

16logger = logging.getLogger('bcdocs') 

17# Terminal punctuation where a space is not needed before. 

18PUNCTUATION_CHARACTERS = ('.', ',', '?', '!', ':', ';') 

19 

20 

21class BaseStyle: 

22 def __init__(self, doc, indent_width=2): 

23 self.doc = doc 

24 self.indent_width = indent_width 

25 self._indent = 0 

26 self.keep_data = True 

27 

28 @property 

29 def indentation(self): 

30 return self._indent 

31 

32 @indentation.setter 

33 def indentation(self, value): 

34 self._indent = value 

35 

36 def new_paragraph(self): 

37 return '\n%s' % self.spaces() 

38 

39 def indent(self): 

40 self._indent += 1 

41 

42 def dedent(self): 

43 if self._indent > 0: 

44 self._indent -= 1 

45 

46 def spaces(self): 

47 return ' ' * (self._indent * self.indent_width) 

48 

49 def bold(self, s): 

50 return s 

51 

52 def ref(self, link, title=None): 

53 return link 

54 

55 def h2(self, s): 

56 return s 

57 

58 def h3(self, s): 

59 return s 

60 

61 def underline(self, s): 

62 return s 

63 

64 def italics(self, s): 

65 return s 

66 

67 def add_trailing_space_to_previous_write(self): 

68 # Adds a trailing space if none exists. This is mainly used for 

69 # ensuring inline code and links are separated from surrounding text. 

70 last_write = self.doc.pop_write() 

71 if last_write is None: 

72 last_write = '' 

73 if last_write != '' and last_write[-1] != ' ': 

74 last_write += ' ' 

75 self.doc.push_write(last_write) 

76 

77 

78class ReSTStyle(BaseStyle): 

79 def __init__(self, doc, indent_width=2): 

80 BaseStyle.__init__(self, doc, indent_width) 

81 self.do_p = True 

82 self.a_href = None 

83 self.list_depth = 0 

84 

85 def new_paragraph(self): 

86 self.doc.write('\n\n%s' % self.spaces()) 

87 

88 def new_line(self): 

89 self.doc.write('\n%s' % self.spaces()) 

90 

91 def _start_inline(self, markup): 

92 # Insert space between any directly adjacent bold and italic inlines to 

93 # avoid situations like ``**abc***def*``. 

94 try: 

95 last_write = self.doc.peek_write() 

96 except IndexError: 

97 pass 

98 else: 

99 if last_write in ('*', '**') and markup in ('*', '**'): 

100 self.doc.write(' ') 

101 self.doc.write(markup) 

102 

103 def _end_inline(self, markup): 

104 # Remove empty and self-closing tags like ``<b></b>`` and ``<b/>``. 

105 # If we simply translate that directly then we end up with something 

106 # like ****, which rst will assume is a heading instead of an empty 

107 # bold. 

108 last_write = self.doc.pop_write() 

109 if last_write == markup: 

110 return 

111 self.doc.push_write(last_write) 

112 self.doc.write(markup) 

113 

114 def start_bold(self, attrs=None): 

115 self._start_inline('**') 

116 

117 def end_bold(self): 

118 self._end_inline('**') 

119 

120 def start_b(self, attrs=None): 

121 self.doc.do_translation = True 

122 self.start_bold(attrs) 

123 

124 def end_b(self): 

125 self.doc.do_translation = False 

126 self.end_bold() 

127 

128 def bold(self, s): 

129 if s: 

130 self.start_bold() 

131 self.doc.write(s) 

132 self.end_bold() 

133 

134 def ref(self, title, link=None): 

135 if link is None: 

136 link = title 

137 self.doc.write(f':doc:`{title} <{link}>`') 

138 

139 def _heading(self, s, border_char): 

140 border = border_char * len(s) 

141 self.new_paragraph() 

142 self.doc.write(f'{border}\n{s}\n{border}') 

143 self.new_paragraph() 

144 

145 def h1(self, s): 

146 self._heading(s, '*') 

147 

148 def h2(self, s): 

149 self._heading(s, '=') 

150 

151 def h3(self, s): 

152 self._heading(s, '-') 

153 

154 def start_italics(self, attrs=None): 

155 self._start_inline('*') 

156 

157 def end_italics(self): 

158 self._end_inline('*') 

159 

160 def italics(self, s): 

161 if s: 

162 self.start_italics() 

163 self.doc.write(s) 

164 self.end_italics() 

165 

166 def start_p(self, attrs=None): 

167 if self.do_p: 

168 self.doc.write('\n\n%s' % self.spaces()) 

169 

170 def end_p(self): 

171 if self.do_p: 

172 self.doc.write('\n\n%s' % self.spaces()) 

173 

174 def start_code(self, attrs=None): 

175 self.doc.do_translation = True 

176 self.add_trailing_space_to_previous_write() 

177 self._start_inline('``') 

178 

179 def end_code(self): 

180 self.doc.do_translation = False 

181 self._end_inline('``') 

182 

183 def code(self, s): 

184 if s: 

185 self.start_code() 

186 self.doc.write(s) 

187 self.end_code() 

188 

189 def start_note(self, attrs=None): 

190 self.new_paragraph() 

191 self.doc.write('.. note::') 

192 self.indent() 

193 self.new_paragraph() 

194 

195 def end_note(self): 

196 self.dedent() 

197 self.new_paragraph() 

198 

199 def start_important(self, attrs=None): 

200 self.new_paragraph() 

201 self.doc.write('.. warning::') 

202 self.indent() 

203 self.new_paragraph() 

204 

205 def end_important(self): 

206 self.dedent() 

207 self.new_paragraph() 

208 

209 def start_danger(self, attrs=None): 

210 self.new_paragraph() 

211 self.doc.write('.. danger::') 

212 self.indent() 

213 self.new_paragraph() 

214 

215 def end_danger(self): 

216 self.dedent() 

217 self.new_paragraph() 

218 

219 def start_a(self, attrs=None): 

220 # Write an empty space to guard against zero whitespace 

221 # before an "a" tag. Example: hi<a>Example</a> 

222 self.add_trailing_space_to_previous_write() 

223 if attrs: 

224 for attr_key, attr_value in attrs: 

225 if attr_key == 'href': 

226 # Removes unnecessary whitespace around the href link. 

227 # Example: <a href=" http://example.com ">Example</a> 

228 self.a_href = attr_value.strip() 

229 self.doc.write('`') 

230 else: 

231 # There are some model documentation that 

232 # looks like this: <a>DescribeInstances</a>. 

233 # In this case we just write out an empty 

234 # string. 

235 self.doc.write(' ') 

236 self.doc.do_translation = True 

237 

238 def link_target_definition(self, refname, link): 

239 self.doc.writeln(f'.. _{refname}: {link}') 

240 

241 def sphinx_reference_label(self, label, text=None): 

242 if text is None: 

243 text = label 

244 if self.doc.target == 'html': 

245 self.doc.write(f':ref:`{text} <{label}>`') 

246 else: 

247 self.doc.write(text) 

248 

249 def _clean_link_text(self): 

250 doc = self.doc 

251 # Pop till we reach the link start character to retrieve link text. 

252 last_write = doc.pop_write() 

253 while not last_write.startswith('`'): 

254 last_write = doc.pop_write() + last_write 

255 if last_write != '': 

256 # Remove whitespace from the start of link text. 

257 if last_write.startswith('` '): 

258 last_write = f'`{last_write[1:].lstrip(" ")}' 

259 doc.push_write(last_write) 

260 

261 def end_a(self, next_child=None): 

262 self.doc.do_translation = False 

263 if self.a_href: 

264 self._clean_link_text() 

265 last_write = self.doc.pop_write() 

266 last_write = last_write.rstrip(' ') 

267 if last_write and last_write != '`': 

268 if ':' in last_write: 

269 last_write = last_write.replace(':', r'\:') 

270 self.doc.push_write(last_write) 

271 self.doc.push_write(' <%s>`__' % self.a_href) 

272 elif last_write == '`': 

273 # Look at start_a(). It will do a self.doc.write('`') 

274 # which is the start of the link title. If that is the 

275 # case then there was no link text. We should just 

276 # use an inline link. The syntax of this is 

277 # `<http://url>`_ 

278 self.doc.push_write('`<%s>`__' % self.a_href) 

279 else: 

280 self.doc.push_write(self.a_href) 

281 self.doc.hrefs[self.a_href] = self.a_href 

282 self.doc.write('`__') 

283 self.a_href = None 

284 

285 def start_i(self, attrs=None): 

286 self.doc.do_translation = True 

287 self.start_italics() 

288 

289 def end_i(self): 

290 self.doc.do_translation = False 

291 self.end_italics() 

292 

293 def start_li(self, attrs=None): 

294 self.new_line() 

295 self.do_p = False 

296 self.doc.write('* ') 

297 

298 def end_li(self): 

299 self.do_p = True 

300 self.new_line() 

301 

302 def li(self, s): 

303 if s: 

304 self.start_li() 

305 self.doc.writeln(s) 

306 self.end_li() 

307 

308 def start_ul(self, attrs=None): 

309 if self.list_depth != 0: 

310 self.indent() 

311 self.list_depth += 1 

312 self.new_paragraph() 

313 

314 def end_ul(self): 

315 self.list_depth -= 1 

316 if self.list_depth != 0: 

317 self.dedent() 

318 self.new_paragraph() 

319 

320 def start_ol(self, attrs=None): 

321 # TODO: Need to control the bullets used for LI items 

322 if self.list_depth != 0: 

323 self.indent() 

324 self.list_depth += 1 

325 self.new_paragraph() 

326 

327 def end_ol(self): 

328 self.list_depth -= 1 

329 if self.list_depth != 0: 

330 self.dedent() 

331 self.new_paragraph() 

332 

333 def start_examples(self, attrs=None): 

334 self.doc.keep_data = False 

335 

336 def end_examples(self): 

337 self.doc.keep_data = True 

338 

339 def start_fullname(self, attrs=None): 

340 self.doc.keep_data = False 

341 

342 def end_fullname(self): 

343 self.doc.keep_data = True 

344 

345 def start_codeblock(self, attrs=None): 

346 self.doc.write('::') 

347 self.indent() 

348 self.new_paragraph() 

349 

350 def end_codeblock(self): 

351 self.dedent() 

352 self.new_paragraph() 

353 

354 def codeblock(self, code): 

355 """ 

356 Literal code blocks are introduced by ending a paragraph with 

357 the special marker ::. The literal block must be indented 

358 (and, like all paragraphs, separated from the surrounding 

359 ones by blank lines). 

360 """ 

361 self.start_codeblock() 

362 self.doc.writeln(code) 

363 self.end_codeblock() 

364 

365 def toctree(self): 

366 if self.doc.target == 'html': 

367 self.doc.write('\n.. toctree::\n') 

368 self.doc.write(' :maxdepth: 1\n') 

369 self.doc.write(' :titlesonly:\n\n') 

370 else: 

371 self.start_ul() 

372 

373 def tocitem(self, item, file_name=None): 

374 if self.doc.target == 'man': 

375 self.li(item) 

376 else: 

377 if file_name: 

378 self.doc.writeln(' %s' % file_name) 

379 else: 

380 self.doc.writeln(' %s' % item) 

381 

382 def hidden_toctree(self): 

383 if self.doc.target == 'html': 

384 self.doc.write('\n.. toctree::\n') 

385 self.doc.write(' :maxdepth: 1\n') 

386 self.doc.write(' :hidden:\n\n') 

387 

388 def hidden_tocitem(self, item): 

389 if self.doc.target == 'html': 

390 self.tocitem(item) 

391 

392 def table_of_contents(self, title=None, depth=None): 

393 self.doc.write('.. contents:: ') 

394 if title is not None: 

395 self.doc.writeln(title) 

396 if depth is not None: 

397 self.doc.writeln(' :depth: %s' % depth) 

398 

399 def start_sphinx_py_class(self, class_name): 

400 self.new_paragraph() 

401 self.doc.write('.. py:class:: %s' % class_name) 

402 self.indent() 

403 self.new_paragraph() 

404 

405 def end_sphinx_py_class(self): 

406 self.dedent() 

407 self.new_paragraph() 

408 

409 def start_sphinx_py_method(self, method_name, parameters=None): 

410 self.new_paragraph() 

411 content = '.. py:method:: %s' % method_name 

412 if parameters is not None: 

413 content += '(%s)' % parameters 

414 self.doc.write(content) 

415 self.indent() 

416 self.new_paragraph() 

417 

418 def end_sphinx_py_method(self): 

419 self.dedent() 

420 self.new_paragraph() 

421 

422 def start_sphinx_py_attr(self, attr_name): 

423 self.new_paragraph() 

424 self.doc.write('.. py:attribute:: %s' % attr_name) 

425 self.indent() 

426 self.new_paragraph() 

427 

428 def end_sphinx_py_attr(self): 

429 self.dedent() 

430 self.new_paragraph() 

431 

432 def write_py_doc_string(self, docstring): 

433 docstring_lines = docstring.splitlines() 

434 for docstring_line in docstring_lines: 

435 self.doc.writeln(docstring_line) 

436 

437 def external_link(self, title, link): 

438 if self.doc.target == 'html': 

439 self.doc.write(f'`{title} <{link}>`_') 

440 else: 

441 self.doc.write(title) 

442 

443 def internal_link(self, title, page): 

444 if self.doc.target == 'html': 

445 self.doc.write(f':doc:`{title} <{page}>`') 

446 else: 

447 self.doc.write(title)