Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/docutils/parsers/rst/roles.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author | shellac |
---|---|
date | Sat, 02 May 2020 07:14:21 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:26e78fe6e8c4 |
---|---|
1 # $Id: roles.py 8347 2019-08-26 12:12:02Z milde $ | |
2 # Author: Edward Loper <edloper@gradient.cis.upenn.edu> | |
3 # Copyright: This module has been placed in the public domain. | |
4 | |
5 """ | |
6 This module defines standard interpreted text role functions, a registry for | |
7 interpreted text roles, and an API for adding to and retrieving from the | |
8 registry. | |
9 | |
10 The interface for interpreted role functions is as follows:: | |
11 | |
12 def role_fn(name, rawtext, text, lineno, inliner, | |
13 options={}, content=[]): | |
14 code... | |
15 | |
16 # Set function attributes for customization: | |
17 role_fn.options = ... | |
18 role_fn.content = ... | |
19 | |
20 Parameters: | |
21 | |
22 - ``name`` is the local name of the interpreted text role, the role name | |
23 actually used in the document. | |
24 | |
25 - ``rawtext`` is a string containing the entire interpreted text construct. | |
26 Return it as a ``problematic`` node linked to a system message if there is a | |
27 problem. | |
28 | |
29 - ``text`` is the interpreted text content, with backslash escapes converted | |
30 to nulls (``\x00``). | |
31 | |
32 - ``lineno`` is the line number where the interpreted text beings. | |
33 | |
34 - ``inliner`` is the Inliner object that called the role function. | |
35 It defines the following useful attributes: ``reporter``, | |
36 ``problematic``, ``memo``, ``parent``, ``document``. | |
37 | |
38 - ``options``: A dictionary of directive options for customization, to be | |
39 interpreted by the role function. Used for additional attributes for the | |
40 generated elements and other functionality. | |
41 | |
42 - ``content``: A list of strings, the directive content for customization | |
43 ("role" directive). To be interpreted by the role function. | |
44 | |
45 Function attributes for customization, interpreted by the "role" directive: | |
46 | |
47 - ``options``: A dictionary, mapping known option names to conversion | |
48 functions such as `int` or `float`. ``None`` or an empty dict implies no | |
49 options to parse. Several directive option conversion functions are defined | |
50 in the `directives` module. | |
51 | |
52 All role functions implicitly support the "class" option, unless disabled | |
53 with an explicit ``{'class': None}``. | |
54 | |
55 - ``content``: A boolean; true if content is allowed. Client code must handle | |
56 the case where content is required but not supplied (an empty content list | |
57 will be supplied). | |
58 | |
59 Note that unlike directives, the "arguments" function attribute is not | |
60 supported for role customization. Directive arguments are handled by the | |
61 "role" directive itself. | |
62 | |
63 Interpreted role functions return a tuple of two values: | |
64 | |
65 - A list of nodes which will be inserted into the document tree at the | |
66 point where the interpreted role was encountered (can be an empty | |
67 list). | |
68 | |
69 - A list of system messages, which will be inserted into the document tree | |
70 immediately after the end of the current inline block (can also be empty). | |
71 """ | |
72 | |
73 __docformat__ = 'reStructuredText' | |
74 | |
75 from docutils import nodes, utils | |
76 from docutils.parsers.rst import directives | |
77 from docutils.parsers.rst.languages import en as _fallback_language_module | |
78 from docutils.utils.code_analyzer import Lexer, LexerError | |
79 | |
80 DEFAULT_INTERPRETED_ROLE = 'title-reference' | |
81 """ | |
82 The canonical name of the default interpreted role. This role is used | |
83 when no role is specified for a piece of interpreted text. | |
84 """ | |
85 | |
86 _role_registry = {} | |
87 """Mapping of canonical role names to role functions. Language-dependent role | |
88 names are defined in the ``language`` subpackage.""" | |
89 | |
90 _roles = {} | |
91 """Mapping of local or language-dependent interpreted text role names to role | |
92 functions.""" | |
93 | |
94 def role(role_name, language_module, lineno, reporter): | |
95 """ | |
96 Locate and return a role function from its language-dependent name, along | |
97 with a list of system messages. If the role is not found in the current | |
98 language, check English. Return a 2-tuple: role function (``None`` if the | |
99 named role cannot be found) and a list of system messages. | |
100 """ | |
101 normname = role_name.lower() | |
102 messages = [] | |
103 msg_text = [] | |
104 | |
105 if normname in _roles: | |
106 return _roles[normname], messages | |
107 | |
108 if role_name: | |
109 canonicalname = None | |
110 try: | |
111 canonicalname = language_module.roles[normname] | |
112 except AttributeError as error: | |
113 msg_text.append('Problem retrieving role entry from language ' | |
114 'module %r: %s.' % (language_module, error)) | |
115 except KeyError: | |
116 msg_text.append('No role entry for "%s" in module "%s".' | |
117 % (role_name, language_module.__name__)) | |
118 else: | |
119 canonicalname = DEFAULT_INTERPRETED_ROLE | |
120 | |
121 # If we didn't find it, try English as a fallback. | |
122 if not canonicalname: | |
123 try: | |
124 canonicalname = _fallback_language_module.roles[normname] | |
125 msg_text.append('Using English fallback for role "%s".' | |
126 % role_name) | |
127 except KeyError: | |
128 msg_text.append('Trying "%s" as canonical role name.' | |
129 % role_name) | |
130 # The canonical name should be an English name, but just in case: | |
131 canonicalname = normname | |
132 | |
133 # Collect any messages that we generated. | |
134 if msg_text: | |
135 message = reporter.info('\n'.join(msg_text), line=lineno) | |
136 messages.append(message) | |
137 | |
138 # Look the role up in the registry, and return it. | |
139 if canonicalname in _role_registry: | |
140 role_fn = _role_registry[canonicalname] | |
141 register_local_role(normname, role_fn) | |
142 return role_fn, messages | |
143 else: | |
144 return None, messages # Error message will be generated by caller. | |
145 | |
146 def register_canonical_role(name, role_fn): | |
147 """ | |
148 Register an interpreted text role by its canonical name. | |
149 | |
150 :Parameters: | |
151 - `name`: The canonical name of the interpreted role. | |
152 - `role_fn`: The role function. See the module docstring. | |
153 """ | |
154 set_implicit_options(role_fn) | |
155 _role_registry[name] = role_fn | |
156 | |
157 def register_local_role(name, role_fn): | |
158 """ | |
159 Register an interpreted text role by its local or language-dependent name. | |
160 | |
161 :Parameters: | |
162 - `name`: The local or language-dependent name of the interpreted role. | |
163 - `role_fn`: The role function. See the module docstring. | |
164 """ | |
165 set_implicit_options(role_fn) | |
166 _roles[name] = role_fn | |
167 | |
168 def set_implicit_options(role_fn): | |
169 """ | |
170 Add customization options to role functions, unless explicitly set or | |
171 disabled. | |
172 """ | |
173 if not hasattr(role_fn, 'options') or role_fn.options is None: | |
174 role_fn.options = {'class': directives.class_option} | |
175 elif 'class' not in role_fn.options: | |
176 role_fn.options['class'] = directives.class_option | |
177 | |
178 def register_generic_role(canonical_name, node_class): | |
179 """For roles which simply wrap a given `node_class` around the text.""" | |
180 role = GenericRole(canonical_name, node_class) | |
181 register_canonical_role(canonical_name, role) | |
182 | |
183 | |
184 class GenericRole(object): | |
185 | |
186 """ | |
187 Generic interpreted text role, where the interpreted text is simply | |
188 wrapped with the provided node class. | |
189 """ | |
190 | |
191 def __init__(self, role_name, node_class): | |
192 self.name = role_name | |
193 self.node_class = node_class | |
194 | |
195 def __call__(self, role, rawtext, text, lineno, inliner, | |
196 options={}, content=[]): | |
197 set_classes(options) | |
198 return [self.node_class(rawtext, text, **options)], [] | |
199 | |
200 | |
201 class CustomRole(object): | |
202 | |
203 """ | |
204 Wrapper for custom interpreted text roles. | |
205 """ | |
206 | |
207 def __init__(self, role_name, base_role, options={}, content=[]): | |
208 self.name = role_name | |
209 self.base_role = base_role | |
210 self.options = None | |
211 if hasattr(base_role, 'options'): | |
212 self.options = base_role.options | |
213 self.content = None | |
214 if hasattr(base_role, 'content'): | |
215 self.content = base_role.content | |
216 self.supplied_options = options | |
217 self.supplied_content = content | |
218 | |
219 def __call__(self, role, rawtext, text, lineno, inliner, | |
220 options={}, content=[]): | |
221 opts = self.supplied_options.copy() | |
222 opts.update(options) | |
223 cont = list(self.supplied_content) | |
224 if cont and content: | |
225 cont += '\n' | |
226 cont.extend(content) | |
227 return self.base_role(role, rawtext, text, lineno, inliner, | |
228 options=opts, content=cont) | |
229 | |
230 | |
231 def generic_custom_role(role, rawtext, text, lineno, inliner, | |
232 options={}, content=[]): | |
233 """""" | |
234 # Once nested inline markup is implemented, this and other methods should | |
235 # recursively call inliner.nested_parse(). | |
236 set_classes(options) | |
237 return [nodes.inline(rawtext, text, **options)], [] | |
238 | |
239 generic_custom_role.options = {'class': directives.class_option} | |
240 | |
241 | |
242 ###################################################################### | |
243 # Define and register the standard roles: | |
244 ###################################################################### | |
245 | |
246 register_generic_role('abbreviation', nodes.abbreviation) | |
247 register_generic_role('acronym', nodes.acronym) | |
248 register_generic_role('emphasis', nodes.emphasis) | |
249 register_generic_role('literal', nodes.literal) | |
250 register_generic_role('strong', nodes.strong) | |
251 register_generic_role('subscript', nodes.subscript) | |
252 register_generic_role('superscript', nodes.superscript) | |
253 register_generic_role('title-reference', nodes.title_reference) | |
254 | |
255 def pep_reference_role(role, rawtext, text, lineno, inliner, | |
256 options={}, content=[]): | |
257 try: | |
258 pepnum = int(utils.unescape(text)) | |
259 if pepnum < 0 or pepnum > 9999: | |
260 raise ValueError | |
261 except ValueError: | |
262 msg = inliner.reporter.error( | |
263 'PEP number must be a number from 0 to 9999; "%s" is invalid.' | |
264 % text, line=lineno) | |
265 prb = inliner.problematic(rawtext, rawtext, msg) | |
266 return [prb], [msg] | |
267 # Base URL mainly used by inliner.pep_reference; so this is correct: | |
268 ref = (inliner.document.settings.pep_base_url | |
269 + inliner.document.settings.pep_file_url_template % pepnum) | |
270 set_classes(options) | |
271 return [nodes.reference(rawtext, 'PEP ' + text, refuri=ref, | |
272 **options)], [] | |
273 | |
274 register_canonical_role('pep-reference', pep_reference_role) | |
275 | |
276 def rfc_reference_role(role, rawtext, text, lineno, inliner, | |
277 options={}, content=[]): | |
278 try: | |
279 if "#" in text: | |
280 rfcnum, section = utils.unescape(text).split("#", 1) | |
281 else: | |
282 rfcnum, section = utils.unescape(text), None | |
283 rfcnum = int(rfcnum) | |
284 if rfcnum < 1: | |
285 raise ValueError | |
286 except ValueError: | |
287 msg = inliner.reporter.error( | |
288 'RFC number must be a number greater than or equal to 1; ' | |
289 '"%s" is invalid.' % text, line=lineno) | |
290 prb = inliner.problematic(rawtext, rawtext, msg) | |
291 return [prb], [msg] | |
292 # Base URL mainly used by inliner.rfc_reference, so this is correct: | |
293 ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum | |
294 if section is not None: | |
295 ref += "#"+section | |
296 set_classes(options) | |
297 node = nodes.reference(rawtext, 'RFC ' + str(rfcnum), refuri=ref, | |
298 **options) | |
299 return [node], [] | |
300 | |
301 register_canonical_role('rfc-reference', rfc_reference_role) | |
302 | |
303 def raw_role(role, rawtext, text, lineno, inliner, options={}, content=[]): | |
304 if not inliner.document.settings.raw_enabled: | |
305 msg = inliner.reporter.warning('raw (and derived) roles disabled') | |
306 prb = inliner.problematic(rawtext, rawtext, msg) | |
307 return [prb], [msg] | |
308 if 'format' not in options: | |
309 msg = inliner.reporter.error( | |
310 'No format (Writer name) is associated with this role: "%s".\n' | |
311 'The "raw" role cannot be used directly.\n' | |
312 'Instead, use the "role" directive to create a new role with ' | |
313 'an associated format.' % role, line=lineno) | |
314 prb = inliner.problematic(rawtext, rawtext, msg) | |
315 return [prb], [msg] | |
316 set_classes(options) | |
317 node = nodes.raw(rawtext, utils.unescape(text, True), **options) | |
318 node.source, node.line = inliner.reporter.get_source_and_line(lineno) | |
319 return [node], [] | |
320 | |
321 raw_role.options = {'format': directives.unchanged} | |
322 | |
323 register_canonical_role('raw', raw_role) | |
324 | |
325 def code_role(role, rawtext, text, lineno, inliner, options={}, content=[]): | |
326 set_classes(options) | |
327 language = options.get('language', '') | |
328 classes = ['code'] | |
329 if 'classes' in options: | |
330 classes.extend(options['classes']) | |
331 if language and language not in classes: | |
332 classes.append(language) | |
333 try: | |
334 tokens = Lexer(utils.unescape(text, True), language, | |
335 inliner.document.settings.syntax_highlight) | |
336 except LexerError as error: | |
337 msg = inliner.reporter.warning(error) | |
338 prb = inliner.problematic(rawtext, rawtext, msg) | |
339 return [prb], [msg] | |
340 | |
341 node = nodes.literal(rawtext, '', classes=classes) | |
342 | |
343 # analyse content and add nodes for every token | |
344 for classes, value in tokens: | |
345 if classes: | |
346 node += nodes.inline(value, value, classes=classes) | |
347 else: | |
348 # insert as Text to decrease the verbosity of the output | |
349 node += nodes.Text(value, value) | |
350 | |
351 return [node], [] | |
352 | |
353 code_role.options = {'class': directives.class_option, | |
354 'language': directives.unchanged} | |
355 | |
356 register_canonical_role('code', code_role) | |
357 | |
358 def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]): | |
359 set_classes(options) | |
360 i = rawtext.find('`') | |
361 text = rawtext.split('`')[1] | |
362 node = nodes.math(rawtext, text, **options) | |
363 return [node], [] | |
364 | |
365 register_canonical_role('math', math_role) | |
366 | |
367 ###################################################################### | |
368 # Register roles that are currently unimplemented. | |
369 ###################################################################### | |
370 | |
371 def unimplemented_role(role, rawtext, text, lineno, inliner, attributes={}): | |
372 msg = inliner.reporter.error( | |
373 'Interpreted text role "%s" not implemented.' % role, line=lineno) | |
374 prb = inliner.problematic(rawtext, rawtext, msg) | |
375 return [prb], [msg] | |
376 | |
377 register_canonical_role('index', unimplemented_role) | |
378 register_canonical_role('named-reference', unimplemented_role) | |
379 register_canonical_role('anonymous-reference', unimplemented_role) | |
380 register_canonical_role('uri-reference', unimplemented_role) | |
381 register_canonical_role('footnote-reference', unimplemented_role) | |
382 register_canonical_role('citation-reference', unimplemented_role) | |
383 register_canonical_role('substitution-reference', unimplemented_role) | |
384 register_canonical_role('target', unimplemented_role) | |
385 | |
386 # This should remain unimplemented, for testing purposes: | |
387 register_canonical_role('restructuredtext-unimplemented-role', | |
388 unimplemented_role) | |
389 | |
390 | |
391 def set_classes(options): | |
392 """ | |
393 Auxiliary function to set options['classes'] and delete | |
394 options['class']. | |
395 """ | |
396 if 'class' in options: | |
397 assert 'classes' not in options | |
398 options['classes'] = options['class'] | |
399 del options['class'] |