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'] |
