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
« 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.
14import logging
16logger = logging.getLogger('bcdocs')
17# Terminal punctuation where a space is not needed before.
18PUNCTUATION_CHARACTERS = ('.', ',', '?', '!', ':', ';')
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
28 @property
29 def indentation(self):
30 return self._indent
32 @indentation.setter
33 def indentation(self, value):
34 self._indent = value
36 def new_paragraph(self):
37 return '\n%s' % self.spaces()
39 def indent(self):
40 self._indent += 1
42 def dedent(self):
43 if self._indent > 0:
44 self._indent -= 1
46 def spaces(self):
47 return ' ' * (self._indent * self.indent_width)
49 def bold(self, s):
50 return s
52 def ref(self, link, title=None):
53 return link
55 def h2(self, s):
56 return s
58 def h3(self, s):
59 return s
61 def underline(self, s):
62 return s
64 def italics(self, s):
65 return s
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)
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
85 def new_paragraph(self):
86 self.doc.write('\n\n%s' % self.spaces())
88 def new_line(self):
89 self.doc.write('\n%s' % self.spaces())
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)
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)
114 def start_bold(self, attrs=None):
115 self._start_inline('**')
117 def end_bold(self):
118 self._end_inline('**')
120 def start_b(self, attrs=None):
121 self.doc.do_translation = True
122 self.start_bold(attrs)
124 def end_b(self):
125 self.doc.do_translation = False
126 self.end_bold()
128 def bold(self, s):
129 if s:
130 self.start_bold()
131 self.doc.write(s)
132 self.end_bold()
134 def ref(self, title, link=None):
135 if link is None:
136 link = title
137 self.doc.write(f':doc:`{title} <{link}>`')
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()
145 def h1(self, s):
146 self._heading(s, '*')
148 def h2(self, s):
149 self._heading(s, '=')
151 def h3(self, s):
152 self._heading(s, '-')
154 def start_italics(self, attrs=None):
155 self._start_inline('*')
157 def end_italics(self):
158 self._end_inline('*')
160 def italics(self, s):
161 if s:
162 self.start_italics()
163 self.doc.write(s)
164 self.end_italics()
166 def start_p(self, attrs=None):
167 if self.do_p:
168 self.doc.write('\n\n%s' % self.spaces())
170 def end_p(self):
171 if self.do_p:
172 self.doc.write('\n\n%s' % self.spaces())
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('``')
179 def end_code(self):
180 self.doc.do_translation = False
181 self._end_inline('``')
183 def code(self, s):
184 if s:
185 self.start_code()
186 self.doc.write(s)
187 self.end_code()
189 def start_note(self, attrs=None):
190 self.new_paragraph()
191 self.doc.write('.. note::')
192 self.indent()
193 self.new_paragraph()
195 def end_note(self):
196 self.dedent()
197 self.new_paragraph()
199 def start_important(self, attrs=None):
200 self.new_paragraph()
201 self.doc.write('.. warning::')
202 self.indent()
203 self.new_paragraph()
205 def end_important(self):
206 self.dedent()
207 self.new_paragraph()
209 def start_danger(self, attrs=None):
210 self.new_paragraph()
211 self.doc.write('.. danger::')
212 self.indent()
213 self.new_paragraph()
215 def end_danger(self):
216 self.dedent()
217 self.new_paragraph()
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
238 def link_target_definition(self, refname, link):
239 self.doc.writeln(f'.. _{refname}: {link}')
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)
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)
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
285 def start_i(self, attrs=None):
286 self.doc.do_translation = True
287 self.start_italics()
289 def end_i(self):
290 self.doc.do_translation = False
291 self.end_italics()
293 def start_li(self, attrs=None):
294 self.new_line()
295 self.do_p = False
296 self.doc.write('* ')
298 def end_li(self):
299 self.do_p = True
300 self.new_line()
302 def li(self, s):
303 if s:
304 self.start_li()
305 self.doc.writeln(s)
306 self.end_li()
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()
314 def end_ul(self):
315 self.list_depth -= 1
316 if self.list_depth != 0:
317 self.dedent()
318 self.new_paragraph()
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()
327 def end_ol(self):
328 self.list_depth -= 1
329 if self.list_depth != 0:
330 self.dedent()
331 self.new_paragraph()
333 def start_examples(self, attrs=None):
334 self.doc.keep_data = False
336 def end_examples(self):
337 self.doc.keep_data = True
339 def start_fullname(self, attrs=None):
340 self.doc.keep_data = False
342 def end_fullname(self):
343 self.doc.keep_data = True
345 def start_codeblock(self, attrs=None):
346 self.doc.write('::')
347 self.indent()
348 self.new_paragraph()
350 def end_codeblock(self):
351 self.dedent()
352 self.new_paragraph()
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()
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()
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)
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')
388 def hidden_tocitem(self, item):
389 if self.doc.target == 'html':
390 self.tocitem(item)
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)
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()
405 def end_sphinx_py_class(self):
406 self.dedent()
407 self.new_paragraph()
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()
418 def end_sphinx_py_method(self):
419 self.dedent()
420 self.new_paragraph()
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()
428 def end_sphinx_py_attr(self):
429 self.dedent()
430 self.new_paragraph()
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)
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)
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)