def apply(self): doc = self.document i = len(doc) - 1 refsect = copyright = None while i >= 0 and isinstance(doc[i], nodes.section): title_words = doc[i][0].astext().lower().split() if 'references' in title_words: refsect = doc[i] break elif 'copyright' in title_words: copyright = i i -= 1 if not refsect: refsect = nodes.section() refsect += nodes.title('', 'References') doc.set_id(refsect) if copyright: # Put the new "References" section before "Copyright": doc.insert(copyright, refsect) else: # Put the new "References" section at end of doc: doc.append(refsect) pending = nodes.pending(references.TargetNotes) refsect.append(pending) self.document.note_pending(pending, 0) pending = nodes.pending(misc.CallBack, details={'callback': self.cleanup_callback}) refsect.append(pending) self.document.note_pending(pending, 1)
def run (self, transform, extraclasses = None): """ extra_classes: classes set on container element """ document = self.state_machine.document extraclasses = extraclasses or [] self.options['directive_name'] = self.name extraclasses.append (self.name) # contents, loa, lof, lot, footnotes container = nodes.container () container['classes'] += self.options.get ('class', []) if 'depth' in self.options: container['toc_depth'] = self.options['depth'] pending = nodes.pending (transform, self.options) document.note_pending (pending) container += pending pending = nodes.pending (parts.EmptySectionRemover) document.note_pending (pending) entries = [] if 'local' in self.options: container['classes'] += ['local'] container['classes'] += map (lambda x: 'local-' + x, extraclasses) entries = [container] elif self.arguments: container['classes'] += extraclasses section = nodes.section () title_text = self.arguments[0] text_nodes, dummy_messages = self.state.inline_text (title_text, self.lineno) title = nodes.title (title_text, '', *text_nodes) title['toc_entry'] = None # default for generated sections is: no toc entry section += title section += pending section += container document.note_implicit_target (section) entries = [section] else: container['classes'] += extraclasses entries = [pending, container] return entries
def run(self): # TODO: error checking meta_name, meta_value = self.arguments # create new pending node, which will: # - hold metadata # - reference transform class which is concerned with this node pending = nodes.pending(self.transform_class) # add content into pending node pending.details['meta_name'] = meta_name pending.details['meta_value'] = meta_value # check if there is already some metadata pending node in the # document tree # TODO: this is not very smart/effective, fix it later meta_pending_registered = False for node in self.state_machine.document.traverse(nodes.pending): if 'meta_name' in node.details: meta_pending_registered = True break # since transformation will process all pending nodes # at once, we register only 1st test metadata pending node, and # this also means that the result generated by pylatest transform # will be located in the place of this first test step directive if not meta_pending_registered: # without this, transformer wouldn't know about this pending node self.state_machine.document.note_pending(pending) # and finally return the pending node as the only result return [pending]
def run(self): aafig_options = dict() image_attrs = dict() own_options_keys = self.own_option_spec.keys() + ['scale'] for (k, v) in self.options.items(): if k in own_options_keys: # convert flags to booleans if v is None: v = True # convert percentage to float if k == 'scale': v = float(v) / 100 aafig_options[k] = v del self.options[k] self.arguments = [''] (image_node,) = directives.images.Image.run(self) if isinstance(image_node, nodes.system_message): return [image_node] text = '\n'.join(self.content) pending_node = nodes.pending(AafigTransform, rawsource=text) pending_node.details.update(dict( image_node = image_node, aafigure_options = aafig_options, )) self.state_machine.document.note_pending(pending_node) return [pending_node]
def run (self): self.options['char'] = self.arguments[0] if len (self.arguments) >= 2: self.options['span'] = self.arguments[1] pending = nodes.pending (parts.DropCapTransform, self.options) self.state_machine.document.note_pending (pending) return [pending]
def class_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Set a "class" attribute on the directive content or the next element. When applied to the next element, a "pending" element is inserted, and a transform does the work later. """ try: class_value = directives.class_option(arguments[0]) except ValueError: error = state_machine.reporter.error( 'Invalid class attribute value for "%s" directive: "%s".' % (name, arguments[0]), nodes.literal_block(block_text, block_text), line=lineno) return [error] node_list = [] if content: container = nodes.Element() state.nested_parse(content, content_offset, container) for node in container: node['classes'].extend(class_value) node_list.extend(container.children) else: pending = nodes.pending(misc.ClassAttribute, {'class': class_value, 'directive': name}, block_text) state_machine.document.note_pending(pending) node_list.append(pending) return node_list
def run(self): if not (self.state_machine.match_titles or isinstance(self.state_machine.node, nodes.sidebar)): raise self.error('The "%s" directive may not be used within ' "topics or body elements." % self.name) document = self.state_machine.document language = languages.get_language(document.settings.language_code) if self.arguments: title_text = self.arguments[0] text_nodes, messages = self.state.inline_text(title_text, self.lineno) title = nodes.title(title_text, "", *text_nodes) else: messages = [] if self.options.has_key("local"): title = None else: title = nodes.title("", language.labels["contents"]) topic = nodes.topic(classes=["contents"]) topic["classes"] += self.options.get("class", []) if self.options.has_key("local"): topic["classes"].append("local") if title: name = title.astext() topic += title else: name = language.labels["contents"] name = nodes.fully_normalize_name(name) if not document.has_name(name): topic["names"].append(name) document.note_implicit_target(topic) pending = nodes.pending(parts.Contents, rawsource=self.block_text) pending.details.update(self.options) document.note_pending(pending) topic += pending return [topic] + messages
def target_notes(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Target footnote generation.""" pending = nodes.pending(references.TargetNotes) state_machine.document.note_pending(pending) nodelist = [pending] return nodelist
def parsemeta(self, match): name = self.parse_field_marker(match) indented, indent, line_offset, blank_finish = \ self.state_machine.get_first_known_indented(match.end()) node = self.meta() pending = nodes.pending(components.Filter, {'component': 'writer', 'format': 'html', 'nodes': [node]}) node['content'] = ' '.join(indented) if not indented: line = self.state_machine.line msg = self.reporter.info( 'No content for meta tag "%s".' % name, nodes.literal_block(line, line), line=self.state_machine.abs_line_number()) return msg, blank_finish tokens = name.split() try: attname, val = utils.extract_name_value(tokens[0])[0] node[attname.lower()] = val except utils.NameValueError: node['name'] = tokens[0] for token in tokens[1:]: try: attname, val = utils.extract_name_value(token)[0] node[attname.lower()] = val except utils.NameValueError, detail: line = self.state_machine.line msg = self.reporter.error( 'Error parsing meta tag attribute "%s": %s.' % (token, detail), nodes.literal_block(line, line), line=self.state_machine.abs_line_number()) return msg, blank_finish
def sectnum(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Automatic section numbering.""" pending = nodes.pending(parts.SectNum) pending.details.update(options) state_machine.document.note_pending(pending) return [pending]
def run(self): node_list = [] if not self.content: pending = nodes.pending(RemoveNext, {"directive": self.name}, self.block_text) self.state_machine.document.note_pending(pending) node_list.append(pending) return node_list
def run(self): tmp = self.options["prefix"] tmp += " " self.options["prefix"] = tmp pending = nodes.pending(parts.SectNum) pending.details.update(self.options) self.state_machine.document.note_pending(pending) return [pending]
def apply(self): language = languages.get_language(self.document.settings.language_code) name = language.labels['contents'] title = nodes.title('', name) topic = nodes.topic('', title, classes=['contents']) name = nodes.fully_normalize_name(name) if not self.document.has_name(name): topic['names'].append(name) self.document.note_implicit_target(topic) pending = nodes.pending(parts.Contents) topic += pending self.document.insert(1, topic) self.document.note_pending(pending)
def contents(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Table of contents.""" if arguments: title_text = arguments[0] text_nodes, messages = state.inline_text(title_text, lineno) title = nodes.title(title_text, '', *text_nodes) else: messages = [] title = None pending = nodes.pending(parts.Contents, {'title': title}, block_text) pending.details.update(options) state_machine.document.note_pending(pending) return [pending] + messages
def contents(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Table of contents. The table of contents is generated in two passes: initial parse and transform. During the initial parse, a 'pending' element is generated which acts as a placeholder, storing the TOC title and any options internally. At a later stage in the processing, the 'pending' element is replaced by a 'topic' element, a title and the table of contents proper. """ if not (state_machine.match_titles or isinstance(state_machine.node, nodes.sidebar)): error = state_machine.reporter.error( 'The "%s" directive may not be used within topics ' 'or body elements.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [error] document = state_machine.document language = languages.get_language(document.settings.language_code) if arguments: title_text = arguments[0] text_nodes, messages = state.inline_text(title_text, lineno) title = nodes.title(title_text, '', *text_nodes) else: messages = [] if options.has_key('local'): title = None else: title = nodes.title('', language.labels['contents']) topic = nodes.topic(classes=['contents']) topic['classes'] += options.get('class', []) if options.has_key('local'): topic['classes'].append('local') if title: name = title.astext() topic += title else: name = language.labels['contents'] name = nodes.fully_normalize_name(name) if not document.has_name(name): topic['names'].append(name) document.note_implicit_target(topic) pending = nodes.pending(parts.Contents, rawsource=block_text) pending.details.update(options) document.note_pending(pending) topic += pending return [topic] + messages
def run (self): if self.arguments: self.options['selector'] = self.arguments[0] if 'language' in self.options: self.options['class'].extend (['language-' + x for x in self.options['language']]) del self.options['language'] pending = nodes.pending (parts.StyleTransform, self.options) self.state_machine.document.note_pending (pending) if self.content: # parse content into pending node self.state.nested_parse (self.content, self.content_offset, pending) return [pending]
def apply(self): language = languages.get_language( self.document.settings.language_code, self.document.reporter ) name = language.labels["contents"] title = nodes.title("", name) topic = nodes.topic("", title, classes=["contents"]) name = nodes.fully_normalize_name(name) if not self.document.has_name(name): topic["names"].append(name) self.document.note_implicit_target(topic) pending = nodes.pending(parts.Contents) topic += pending self.document.insert(1, topic) self.document.note_pending(pending)
def __call__(self, typ, rawtext, text, lineno, inliner, options={},\ content=[]): """ When a ``cite`` role is encountered, we replace it with a ``docutils.nodes.pending`` node that uses a ``CitationTrasform`` for generating the proper citation reference representation during the resolve_xref phase. """ rnodes = super(CitationXRefRole, self).__call__(typ, rawtext, text, lineno, inliner, options, content) rootnode = rnodes[0][0] env = inliner.document.settings.env citations = env.domains['cite'].citations # Get the config at this point in the document config = {} for opt in ['style', 'brackets', 'separator', 'sort', 'sort_compress']: config[opt] = env.temp_data.get( "cite_%s" % opt, env.domaindata['cite']['conf'].get(opt, DEFAULT_CONF[opt])) if typ == "cite:text": # A ``text`` citation is unique because it doesn't reference a cite-key keys = [] pre, post = text, '' else: keys, pre, post = parse_keys(text) for key in keys: if citations.get(key) is None: env.warn(env.docname, "cite-key `%s` not found in bibtex file" % key, lineno) continue env.domaindata['cite']['keys'].add(key) data = { 'keys': keys, 'pre': pre, 'post': post, 'typ': typ, 'global_keys': env.domaindata['cite']['keys'], 'config': config } rootnode += nodes.pending(CitationTransform, data) return [rootnode], []
def run(self): if self.arguments: self.options['selector'] = self.arguments[0] if 'language' in self.options: self.options['class'].extend( ['language-' + x for x in self.options['language']]) del self.options['language'] pending = nodes.pending(parts.StyleTransform, self.options) self.state_machine.document.note_pending(pending) if self.content: # parse content into pending node self.state.nested_parse(self.content, self.content_offset, pending) return [pending]
def class_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """""" class_value = nodes.make_id(arguments[0]) if class_value: pending = nodes.pending(misc.ClassAttribute, {'class': class_value, 'directive': name}, block_text) state_machine.document.note_pending(pending) return [pending] else: error = state_machine.reporter.error( 'Invalid class attribute value for "%s" directive: %s' % (name, arguments[0]), nodes.literal_block(block_text, block_text), line=lineno) return [error]
def run(self): # css class is the same as the directive name classes = [self.name] if self.arguments: try: classes.extend(directives.class_option(self.arguments[0])) except ValueError: raise self.error( 'Invalid class attribute value for "%s" directive: "%s".' % (self.name, self.arguments[0]) ) pending = nodes.pending( BlockLines, {"directive": self.name, "class": classes, "allpage": self.allpage}, self.block_text ) self.state_machine.document.note_pending(pending) return [pending]
def result_nodes( self, document: nodes.document, env: BuildEnvironment, node: nodes.Element, is_ref: bool ) -> Tuple[List[nodes.Node], List[nodes.system_message]]: """ When a ``cite`` role is encountered, we replace it with a ``docutils.nodes.pending`` node that uses a ``CitationTransform`` for generating the proper citation reference representation during the resolve_xref phase. """ domain = cast(CitationDomain, env.get_domain('cite')) # Get the config at this point in the document config = {} for opt in ['style', 'brackets', 'separator', 'sort', 'sort_compress']: config[opt] = env.temp_data.get( "cite_%s" % opt, env.domaindata['cite']['conf'].get(opt, DEFAULT_CONF[opt])) if self.name == "cite:text": # A ``text`` citation is unique because it doesn't reference a # cite-key keys = [] pre, post = self.text, '' else: keys, pre, post = parse_keys(self.text) for key in keys: if domain.citations.get(key) is None: logger.warning("cite-key `%s` not found in bibtex file" % key, location=(env.docname, self.lineno)) continue env.domaindata['cite']['keys'][key] = None env.domaindata['cite']['keys'] = sort_references( env.domaindata['cite']['keys'], domain.citations) data = { 'keys': keys, 'pre': pre, 'post': post, 'typ': self.name, 'global_keys': env.domaindata['cite']['keys'], 'config': config } node += nodes.pending(CitationTransform, data) return [node], []
def class_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Set a "class" attribute on the next element. A "pending" element is inserted, and a transform does the work later. """ try: class_value = directives.class_option(arguments[0]) except ValueError: error = state_machine.reporter.error( 'Invalid class attribute value for "%s" directive: "%s".' % (name, arguments[0]), nodes.literal_block(block_text, block_text), line=lineno, ) return [error] pending = nodes.pending(misc.ClassAttribute, {"class": class_value, "directive": name}, block_text) state_machine.document.note_pending(pending) return [pending]
def class_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """""" class_value = nodes.make_id(arguments[0]) if class_value: pending = nodes.pending(misc.ClassAttribute, { 'class': class_value, 'directive': name }, block_text) state_machine.document.note_pending(pending) return [pending] else: error = state_machine.reporter.error( 'Invalid class attribute value for "%s" directive: %s' % (name, arguments[0]), nodes.literal_block(block_text, block_text), line=lineno) return [error]
def run(self): node = addnodes.only() node.document = self.state.document set_source_info(self, node) node['expr'] = 'iguide' class_value = ['iguide', self.arguments[0]] pending = nodes.pending(misc.ClassAttribute, {'class': class_value, 'directive': self.name}, self.block_text) self.state_machine.document.note_pending(pending) node += pending self.state.nested_parse(self.content, self.content_offset, node, match_titles=1) return [node]
def parsemeta(self, match): name = self.parse_field_marker(match) name = utils.unescape(utils.escape2null(name)) ( indented, indent, line_offset, blank_finish, ) = self.state_machine.get_first_known_indented(match.end()) node = self.meta() pending = nodes.pending( components.Filter, { "component": "writer", "format": "html", "nodes": [node] }, ) node["content"] = utils.unescape(utils.escape2null(" ".join(indented))) if not indented: line = self.state_machine.line msg = self.reporter.info('No content for meta tag "%s".' % name, nodes.literal_block(line, line)) return msg, blank_finish tokens = name.split() try: attname, val = utils.extract_name_value(tokens[0])[0] node[attname.lower()] = val except utils.NameValueError: node["name"] = tokens[0] for token in tokens[1:]: try: attname, val = utils.extract_name_value(token)[0] node[attname.lower()] = val except utils.NameValueError as detail: line = self.state_machine.line msg = self.reporter.error( 'Error parsing meta tag attribute "%s": %s.' % (token, detail), nodes.literal_block(line, line), ) return msg, blank_finish self.document.note_pending(pending) return pending, blank_finish
def run(self): if not Initialized: # FIXME: Better way to handle one-time initialization? init(self.state.document.settings, self.state.document.reporter) os.chdir(BTestBase) self.assert_has_content() document = self.state_machine.document tag = self.arguments[0] if not tag in Tests: import sys test = Test() test.tag = tag test.path = os.path.join(BTestTests, tag + ".btest") test.parts = 0 Tests[tag] = test test = Tests[tag] test.parts += 1 part = test.parts # Save the test. if part == 1: file = test.path else: file = test.path + "#%d" % part out = open(file, "w") for line in self.content: out.write("%s\n" % line) out.close() details = (test, part) pending = nodes.pending(BTestTransform, details, rawsource=self.block_text) document.note_pending(pending) return [pending]
def run(self): try: class_value = directives.class_option(self.arguments[0]) except ValueError: raise self.error('Invalid class attribute value for "%s" directive: "%s".' % (self.name, self.arguments[0])) node_list = [] if self.content: container = nodes.Element() self.state.nested_parse(self.content, self.content_offset, container) for node in container: node["classes"].extend(class_value) node_list.extend(container.children) else: pending = nodes.pending( misc.ClassAttribute, {"class": class_value, "directive": self.name}, self.block_text ) self.state_machine.document.note_pending(pending) node_list.append(pending) return node_list
def apply(self): try: #incompatible API change in docutils language = languages.get_language( self.document.settings.language_code, None) except TypeError: language = languages.get_language( self.document.settings.language_code) name = language.labels['contents'] title = nodes.title('', name) topic = nodes.topic('', title, classes=['contents']) name = nodes.fully_normalize_name(name) if not self.document.has_name(name): topic['names'].append(name) self.document.note_implicit_target(topic) pending = nodes.pending(parts.Contents) topic += pending self.document.insert(1, topic) self.document.note_pending(pending)
def __call__(self, typ, rawtext, text, lineno, inliner, options={}, \ content=[]): """ When a ``cite`` role is encountered, we replace it with a ``docutils.nodes.pending`` node that uses a ``CitationTrasform`` for generating the proper citation reference representation during the resolve_xref phase. """ rnodes = super(CitationXRefRole, self).__call__(typ, rawtext, text, lineno, inliner, options, content) rootnode = rnodes[0][0] env = inliner.document.settings.env citations = env.domains['cite'].citations # Get the config at this point in the document config = {} for opt in ['style', 'brackets', 'separator', 'sort', 'sort_compress']: config[opt] = env.temp_data.get("cite_%s" % opt, env.domaindata['cite']['conf'].get(opt, DEFAULT_CONF[opt])) if typ == "cite:text": # A ``text`` citation is unique because it doesn't reference a cite-key keys = [] pre, post = text, '' else: keys, pre, post = parse_keys(text) for key in keys: if citations.get(key) is None: env.warn(env.docname, "cite-key `%s` not found in bibtex file" % key, lineno) continue env.domaindata['cite']['keys'].add(key) env.domaindata['cite']['keys'] = sort_references(env.domaindata['cite']['keys'], citations) data = {'keys': keys, 'pre': pre, 'post': post, 'typ': typ, 'global_keys': env.domaindata['cite']['keys'], 'config': config} rootnode += nodes.pending(CitationTransform, data) return [rootnode], []
def apply(self) -> None: if not Path(self.document["source"]).match("pep-*"): return # not a PEP file, exit early # Create the contents placeholder section contents_section = nodes.section("") if not self.document.has_name("contents"): contents_section["names"].append("contents") self.document.note_implicit_target(contents_section) # Add a table of contents builder pending = nodes.pending(Contents) contents_section += pending self.document.note_pending(pending) # Insert the toc after title and PEP headers self.document.children[0].insert(2, contents_section) # Add a horizontal rule before contents transition = nodes.transition() self.document[0].insert(2, transition)
def run(self): if not (self.state_machine.match_titles or isinstance(self.state_machine.node, nodes.sidebar)): raise self.error('The "%s" directive may not be used within ' 'topics or body elements.' % self.name) document = self.state_machine.document language = languages.get_language(document.settings.language_code, document.reporter) if self.arguments: title_text = self.arguments[0] text_nodes, messages = self.state.inline_text( title_text, self.lineno) title = nodes.title(title_text, '', *text_nodes) else: messages = [] if 'local' in self.options: title = None else: title = nodes.title('', language.labels['contents']) topic = nodes.topic(classes=['contents']) topic['classes'] += self.options.get('class', []) # the latex2e writer needs source and line for a warning: src, srcline = self.state_machine.get_source_and_line() topic.source = src topic.line = srcline - 1 if 'local' in self.options: topic['classes'].append('local') if title: name = title.astext() topic += title else: name = language.labels['contents'] name = nodes.fully_normalize_name(name) if not document.has_name(name): topic['names'].append(name) document.note_implicit_target(topic) pending = nodes.pending(parts.Contents, rawsource=self.block_text) pending.details.update(self.options) document.note_pending(pending) topic += pending return [topic] + messages
def __call__(self, typ, rawtext, text, lineno, inliner, options={}, content=[]): """ When a ``cite`` role is encountered, we replace it with a ``docutils.nodes.pending`` node that uses a ``CitationTrasform`` for generating the proper citation reference representation during the resolve_xref phase. """ rnodes = super(CitationXRefRole, self).__call__(typ, rawtext, text, lineno, inliner, options, content) rootnode = rnodes[0][0] env = inliner.document.settings.env citations = env.domains["cite"].citations # Get the config at this point in the document config = {} for opt in ["style", "brackets", "separator", "sort", "sort_compress"]: config[opt] = env.temp_data.get("cite_%s" % opt, env.domaindata["cite"]["conf"].get(opt, DEFAULT_CONF[opt])) if typ == "cite:text": # A ``text`` citation is unique because it doesn't reference a cite-key keys = [] pre, post = text, "" else: keys, pre, post = parse_keys(text) for key in keys: if citations.get(key) is None: env.warn(env.docname, "cite-key `%s` not found in bibtex file" % key, lineno) continue env.domaindata["cite"]["keys"].add(key) data = { "keys": keys, "pre": pre, "post": post, "typ": typ, "global_keys": env.domaindata["cite"]["keys"], "config": config, } rootnode += nodes.pending(CitationTransform, data) return [rootnode], []
def run(self): if not (self.state_machine.match_titles or isinstance(self.state_machine.node, nodes.sidebar)): raise self.error('The "%s" directive may not be used within ' 'topics or body elements.' % self.name) document = self.state_machine.document language = languages.get_language(document.settings.language_code, document.reporter) if self.arguments: title_text = self.arguments[0] text_nodes, messages = self.state.inline_text(title_text, self.lineno) title = nodes.title(title_text, '', *text_nodes) else: messages = [] if 'local' in self.options: title = None else: title = nodes.title('', language.labels['contents']) topic = nodes.topic(classes=['contents']) topic['classes'] += self.options.get('class', []) # the latex2e writer needs source and line for a warning: src, srcline = self.state_machine.get_source_and_line() topic.source = src topic.line = srcline - 1 if 'local' in self.options: topic['classes'].append('local') if title: name = title.astext() topic += title else: name = language.labels['contents'] name = nodes.fully_normalize_name(name) if not document.has_name(name): topic['names'].append(name) document.note_implicit_target(topic) pending = nodes.pending(parts.Contents, rawsource=self.block_text) pending.details.update(self.options) document.note_pending(pending) topic += pending return [topic] + messages
def index_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): #pending = nodes.pending(EffTransformer.Index, {'entries': content}) #state_machine.document.note_pending(pending) #return [pending] # XXX entries = [] message_set = [] for entry in content: levels = re_index_levels.split(entry) tmp = [] for level in levels: textnodes, messages = state.inline_text(level, lineno) entry_level = index_entry_level(level, '', *textnodes) tmp.append(entry_level) message_set.extend(messages) index = index_entry(entry, *tmp) entries.append(index) pending = nodes.pending(EffTransformer.Index, {'entries': entries}) state_machine.document.note_pending(pending) return [pending] + message_set
def class_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Set a "class" attribute on the next element. A "pending" element is inserted, and a transform does the work later. """ try: class_value = directives.class_option(arguments[0]) except ValueError: error = state_machine.reporter.error( 'Invalid class attribute value for "%s" directive: "%s".' % (name, arguments[0]), nodes.literal_block(block_text, block_text), line=lineno) return [error] pending = nodes.pending(misc.ClassAttribute, { 'class': class_value, 'directive': name }, block_text) state_machine.document.note_pending(pending) return [pending]
def run(self): details = {} if 'depth' in self.options: details['toc_depth'] = self.options['depth'] container = nodes.container() if self.arguments: container += nodes.inline('', self.arguments[0]) self.state.nested_parse(self.content, self.content_offset, container) container['classes'] += self.options.get('class', []) if container.astext(): details['content'] = container else: details['content'] = None # flag: supress toc entry pending = nodes.pending(parts.TocEntryTransform, details) self.state_machine.document.note_pending(pending) return [pending]
def run (self): details = {} if 'depth' in self.options: details['toc_depth'] = self.options['depth'] container = nodes.container () if self.arguments: container += nodes.inline ('', self.arguments[0]) self.state.nested_parse (self.content, self.content_offset, container) container['classes'] += self.options.get ('class', []) if container.astext (): details['content'] = container else: details['content'] = None # flag: supress toc entry pending = nodes.pending (parts.TocEntryTransform, details) self.state_machine.document.note_pending (pending) return [pending]
def run(self) -> List[nodes.Node]: try: rjs_id = self.arguments[0] except ValueError: raise self.error( 'Invalid class attribute value for "%s" directive: "%s".' % (self.name, self.arguments[0])) node_list = [] if self.content: container = nodes.Element() self.state.nested_parse(self.content, self.content_offset, container) for node in container: node.attributes['revealjs-id'] = rjs_id node_list.extend(container.children) else: pending = nodes.pending(RevealjsIdAttribute, { 'revealjs-id': rjs_id, 'directive': self.name }, self.block_text) self.state_machine.document.note_pending(pending) node_list.append(pending) return node_list
def run(self): try: class_value = directives.class_option(self.arguments[0]) except ValueError: raise self.error( 'Invalid class attribute value for "%s" directive: "%s".' % (self.name, self.arguments[0])) node_list = [] if self.content: container = nodes.Element() self.state.nested_parse(self.content, self.content_offset, container) for node in container: node['classes'].extend(class_value) node_list.extend(container.children) else: pending = nodes.pending(misc.ClassAttribute, { 'class': class_value, 'directive': self.name }, self.block_text) self.state_machine.document.note_pending(pending) node_list.append(pending) return node_list
def run(self): # each pylatest directive in the rst document has mandatory action id # (starts from 1), so there is either just one or no pylatest directive # with action_id == 1 # note: # action is couple of test step and result with the same action_id action_id = int(self.arguments[0]) # first of all, parse text content of this directive # into anonymous node element (can't be used directly in the tree) node = nodes.Element() # include HACK: link to the referred test case # TODO: use a proper referece (nested parse?) # TODO: the final solutions is a working include though if 'include' in self.options: ref_tc, ref_action = str(self.options['include']).split(":", 2) text_content = "See {0}, action {1}".format(ref_tc, ref_action) node += nodes.paragraph(text=text_content) else: self.state.nested_parse(self.content, self.content_offset, node) # create new pending node, which: # - holds actual data (parsed content of the directive) # - references transform class which is concerned with this node. # - name of the directive (test_step or test_result) pending = nodes.pending(self.transform_class) # add content into pending node pending.details['nodes'] = node pending.details['action_id'] = action_id pending.details['action_name'] = self.name # since pylatest transformation will process all pylatest pending nodes # at once, we register only 1st test step pending node, and # this also means that the result generated by pylatest transform # will be located in the place of this first test step directive if action_id == 1 and self.name == "test_step": # without this, transformer wouldn't know about this pending node self.state_machine.document.note_pending(pending) # and finally return the pending node as the only result return [pending]
def apply(self): if not len(self.document): # @@@ replace these DataErrors with proper system messages raise DataError('Document tree is empty.') header = self.document[0] if not isinstance(header, nodes.field_list) or \ 'rfc2822' not in header['classes']: raise DataError('Document does not begin with an RFC-2822 ' 'header; it is not a PEP.') pep = None for field in header: if field[0].astext().lower() == 'pep': # should be the first field value = field[1].astext() try: pep = int(value) cvs_url = self.pep_cvs_url % pep except ValueError: pep = value cvs_url = None msg = self.document.reporter.warning( '"PEP" header must contain an integer; "%s" is an ' 'invalid value.' % pep, base_node=field) msgid = self.document.set_id(msg) prb = nodes.problematic(value, value or '(none)', refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) if len(field[1]): field[1][0][:] = [prb] else: field[1] += nodes.paragraph('', '', prb) break if pep is None: raise DataError('Document does not contain an RFC-2822 "PEP" ' 'header.') if pep == 0: # Special processing for PEP 0. pending = nodes.pending(peps.PEPZero) self.document.insert(1, pending) self.document.note_pending(pending) if len(header) < 2 or header[1][0].astext().lower() != 'title': raise DataError('No title!') for field in header: name = field[0].astext().lower() body = field[1] if len(body) > 1: raise DataError('PEP header field body contains multiple ' 'elements:\n%s' % field.pformat(level=1)) elif len(body) == 1: if not isinstance(body[0], nodes.paragraph): raise DataError('PEP header field body may only contain ' 'a single paragraph:\n%s' % field.pformat(level=1)) elif name == 'last-modified': date = time.strftime( '%d-%b-%Y', time.localtime(os.stat(self.document['source'])[8])) if cvs_url: body += nodes.paragraph( '', '', nodes.reference('', date, refuri=cvs_url)) else: # empty continue para = body[0] if name in ('author', 'bdfl-delegate', 'sponsor'): for node in para: if isinstance(node, nodes.reference): node.replace_self(peps.mask_email(node)) elif name == 'discussions-to': for node in para: if isinstance(node, nodes.reference): node.replace_self(peps.mask_email(node, pep)) elif name in ('replaces', 'superseded-by', 'requires'): newbody = [] space = nodes.Text(' ') for refpep in re.split(r',?\s+', body.astext()): pepno = int(refpep) newbody.append(nodes.reference( refpep, refpep, refuri=(self.document.settings.pep_base_url + self.pep_url % pepno))) newbody.append(space) para[:] = newbody[:-1] # drop trailing space elif name == 'last-modified': utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) if cvs_url: date = para.astext() para[:] = [nodes.reference('', date, refuri=cvs_url)] elif name == 'content-type': pep_type = para.astext() uri = self.document.settings.pep_base_url + self.pep_url % 12 para[:] = [nodes.reference('', pep_type, refuri=uri)] elif name == 'version' and len(body): utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions)
def run(self): pending = nodes.pending(references.TargetNotes) self.add_name(pending) pending.details.update(self.options) self.state_machine.document.note_pending(pending) return [pending]
def apply(self): pending = nodes.pending(parts.Contents, {'title': None}) self.document.insert(1, pending) self.document.note_pending(pending)
def run(self): pending = nodes.pending(references.TargetNotes) pending.details.update(self.options) self.state_machine.document.note_pending(pending) nodelist = [pending] return nodelist
def run(self): if len(self.arguments) > 0: try: class_value = directives.class_option(self.arguments[0]) except ValueError: raise self.error( 'Invalid class attribute value for "%s" directive: "%s".' % (self.name, self.arguments[0])) else: class_value = None if 'attributes' in self.options and self.options[ 'attributes'] is not None: try: attributes = ast.literal_eval(self.options['attributes']) except ValueError: raise self.error('Could not parse attribute string: "%s"' % self.options['attributes']) attributes = None else: attributes = None if 'slide-attributes' in self.options and self.options[ 'slide-attributes'] is not None: try: slide_attributes = ast.literal_eval( self.options['slide-attributes']) except ValueError: raise self.error( 'Could not parse slide-attribute string: "%s"' % self.options['slide-attributes']) slide_attributes = None else: slide_attributes = None node_list = [] if self.content: container = nodes.Element() self.state.nested_parse(self.content, self.content_offset, container) for node in container: if class_value is not None: node['classes'].extend(class_value) if attributes is not None: if 'attributes' in node: node['attributes'].update(attributes) else: node['attributes'] = attributes if slide_attributes is not None: if 'slide-attributes' in node: node['slide-attributes'].update(slide_attributes) else: node['slide-attributes'] = slide_attributes node_list.extend(container.children) else: if 'attributes' in self.options and self.options[ 'attributes'] is not None: try: attributes = ast.literal_eval(self.options['attributes']) except ValueError: raise self.error('Could not parse attribute string: "%s"' % self.options['attributes']) attributes = None else: attributes = None if 'slide-attributes' in self.options and self.options[ 'slide-attributes'] is not None: try: slide_attributes = ast.literal_eval( self.options['slide-attributes']) except ValueError: raise self.error( 'Could not parse slide-attribute string: "%s"' % self.options['slide-attributes']) slide_attributes = None else: slide_attributes = None pending = nodes.pending( ClassAttribute2, { 'class': class_value, 'directive': self.name, 'attributes': attributes, 'slide-attributes': slide_attributes }, self.block_text) self.state_machine.document.note_pending(pending) node_list.append(pending) return node_list
def apply(self): if not len(self.document): # @@@ replace these DataErrors with proper system messages raise DataError("Document tree is empty.") header = self.document[0] if ( not isinstance(header, nodes.field_list) or "rfc2822" not in header["classes"] ): raise DataError( "Document does not begin with an RFC-2822 " "header; it is not a PEP." ) pep = None for field in header: if field[0].astext().lower() == "pep": # should be the first field value = field[1].astext() try: pep = int(value) cvs_url = self.pep_cvs_url % pep except ValueError: pep = value cvs_url = None msg = self.document.reporter.warning( '"PEP" header must contain an integer; "%s" is an ' "invalid value." % pep, base_node=field, ) msgid = self.document.set_id(msg) prb = nodes.problematic(value, value or "(none)", refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) if len(field[1]): field[1][0][:] = [prb] else: field[1] += nodes.paragraph("", "", prb) break if pep is None: raise DataError('Document does not contain an RFC-2822 "PEP" ' "header.") if pep == 0: # Special processing for PEP 0. pending = nodes.pending(PEPZero) self.document.insert(1, pending) self.document.note_pending(pending) if len(header) < 2 or header[1][0].astext().lower() != "title": raise DataError("No title!") for field in header: name = field[0].astext().lower() body = field[1] if len(body) > 1: raise DataError( "PEP header field body contains multiple " "elements:\n%s" % field.pformat(level=1) ) elif len(body) == 1: if not isinstance(body[0], nodes.paragraph): raise DataError( "PEP header field body may only contain " "a single paragraph:\n%s" % field.pformat(level=1) ) elif name == "last-modified": date = time.strftime( "%d-%b-%Y", time.localtime(os.stat(self.document["source"])[8]) ) if cvs_url: body += nodes.paragraph( "", "", nodes.reference("", date, refuri=cvs_url) ) else: # empty continue para = body[0] if name == "author": for node in para: if isinstance(node, nodes.reference): node.replace_self(mask_email(node)) elif name == "discussions-to": for node in para: if isinstance(node, nodes.reference): node.replace_self(mask_email(node, pep)) elif name in ("replaces", "replaced-by", "requires"): newbody = [] space = nodes.Text(" ") for refpep in re.split(r",?\s+", body.astext()): pepno = int(refpep) newbody.append( nodes.reference( refpep, refpep, refuri=( self.document.settings.pep_base_url + self.pep_url % pepno ), ) ) newbody.append(space) para[:] = newbody[:-1] # drop trailing space elif name == "last-modified": utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) if cvs_url: date = para.astext() para[:] = [nodes.reference("", date, refuri=cvs_url)] elif name == "content-type": pep_type = para.astext() uri = self.document.settings.pep_base_url + self.pep_url % 12 para[:] = [nodes.reference("", pep_type, refuri=uri)] elif name == "version" and len(body): utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions)
def apply(self) -> None: if not Path(self.document["source"]).match("pep-*"): return # not a PEP file, exit early if not len(self.document): raise PEPParsingError("Document tree is empty.") header = self.document[0] if not isinstance( header, nodes.field_list) or "rfc2822" not in header["classes"]: raise PEPParsingError( "Document does not begin with an RFC-2822 header; it is not a PEP." ) # PEP number should be the first field pep_field = header[0] if pep_field[0].astext().lower() != "pep": raise PEPParsingError( "Document does not contain an RFC-2822 'PEP' header!") # Extract PEP number value = pep_field[1].astext() try: pep_num = int(value) except ValueError: raise PEPParsingError( f"'PEP' header must contain an integer. '{value}' is invalid!") # Special processing for PEP 0. if pep_num == 0: pending = nodes.pending(pep_zero.PEPZero) self.document.insert(1, pending) self.document.note_pending(pending) # If there are less than two headers in the preamble, or if Title is absent if len(header) < 2 or header[1][0].astext().lower() != "title": raise PEPParsingError("No title!") fields_to_remove = [] for field in header: name = field[0].astext().lower() body = field[1] if len(body) == 0: # body is empty continue elif len(body) > 1: msg = f"PEP header field body contains multiple elements:\n{field.pformat(level=1)}" raise PEPParsingError(msg) elif not isinstance(body[0], nodes.paragraph): # len(body) == 1 msg = f"PEP header field body may only contain a single paragraph:\n{field.pformat(level=1)}" raise PEPParsingError(msg) para = body[0] if name in {"author", "bdfl-delegate", "pep-delegate", "sponsor"}: # mask emails for node in para: if not isinstance(node, nodes.reference): continue node.replace_self(_mask_email(node)) elif name in {"discussions-to", "resolution", "post-history"}: # Prettify mailing list and Discourse links for node in para: if (not isinstance(node, nodes.reference) or not node["refuri"]): continue # Have known mailto links link to their main list pages if node["refuri"].lower().startswith("mailto:"): node["refuri"] = _generate_list_url(node["refuri"]) parts = node["refuri"].lower().split("/") if len(parts) <= 2 or parts[2] not in LINK_PRETTIFIERS: continue pretty_title = _make_link_pretty(str(node["refuri"])) if name == "post-history": node["reftitle"] = pretty_title else: node[0] = nodes.Text(pretty_title) elif name in {"replaces", "superseded-by", "requires"}: # replace PEP numbers with normalised list of links to PEPs new_body = [] for pep_str in re.split(r",?\s+", body.astext()): target = self.document.settings.pep_url.format( int(pep_str)) new_body += [ nodes.reference("", pep_str, refuri=target), nodes.Text(", ") ] para[:] = new_body[:-1] # drop trailing space elif name == "topic": new_body = [] for topic_name in body.astext().split(","): if topic_name: target = f"/topic/{topic_name.lower().strip()}/" new_body += [ nodes.reference("", topic_name, refuri=target), nodes.Text(", "), ] if new_body: para[:] = new_body[:-1] # Drop trailing space/comma elif name in {"last-modified", "content-type", "version"}: # Mark unneeded fields fields_to_remove.append(field) # Remove any trailing commas and whitespace in the headers if para and isinstance(para[-1], nodes.Text): last_node = para[-1] if last_node.astext().strip() == ",": last_node.parent.remove(last_node) else: para[-1] = last_node.rstrip().rstrip(",") # Remove unneeded fields for field in fields_to_remove: field.parent.remove(field)
def run(self): pending = nodes.pending(parts.SectNum) pending.details.update(self.options) self.state_machine.document.note_pending(pending) return [pending]
def apply(self): self.document.settings.rep_base_url = 'http://ros.org/reps/' if not len(self.document): # @@@ replace these DataErrors with proper system messages raise DataError('Document tree is empty.') header = self.document[0] if not isinstance(header, nodes.field_list) or \ 'rfc2822' not in header['classes']: raise DataError('Document does not begin with an RFC-2822 ' 'header; it is not a REP.') rep = None for field in header: if field[0].astext().lower() == 'rep': # should be the first field value = field[1].astext() try: rep = int(value) repo_url = self.rep_git_url % rep except ValueError: rep = value repo_url = None msg = self.document.reporter.warning( '"REP" header must contain an integer; "%s" is an ' 'invalid value.' % rep, base_node=field) msgid = self.document.set_id(msg) prb = nodes.problematic(value, value or '(none)', refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) if len(field[1]): field[1][0][:] = [prb] else: field[1] += nodes.paragraph('', '', prb) break if rep is None: raise DataError('Document does not contain an RFC-2822 "REP" ' 'header.') if rep == 0: # Special processing for REP 0. pending = nodes.pending(REPZero) self.document.insert(1, pending) self.document.note_pending(pending) if len(header) < 2 or header[1][0].astext().lower() != 'title': raise DataError('No title!') for field in header: name = field[0].astext().lower() body = field[1] if len(body) > 1: raise DataError('REP header field body contains multiple ' 'elements:\n%s' % field.pformat(level=1)) elif len(body) == 1: if not isinstance(body[0], nodes.paragraph): raise DataError('REP header field body may only contain ' 'a single paragraph:\n%s' % field.pformat(level=1)) elif name == 'last-modified': date = time.strftime( '%d-%b-%Y', time.localtime(os.stat(self.document['source'])[8])) if repo_url: body += nodes.paragraph( '', '', nodes.reference('', date, refuri=repo_url)) else: # empty continue para = body[0] if name == 'author': for node in para: if isinstance(node, nodes.reference): node.replace_self(mask_email(node)) elif name == 'discussions-to': for node in para: if isinstance(node, nodes.reference): node.replace_self(mask_email(node, rep)) elif name in ('replaces', 'replaced-by', 'requires'): newbody = [] space = nodes.Text(' ') for refrep in re.split(',?\s+', body.astext()): repno = int(refrep) newbody.append( nodes.reference( refrep, refrep, refuri=(self.document.settings.rep_base_url + self.rep_url % repno))) newbody.append(space) para[:] = newbody[:-1] # drop trailing space elif name == 'last-modified': utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) if repo_url: date = para.astext() para[:] = [nodes.reference('', date, refuri=repo_url)] elif name == 'content-type': rep_type = para.astext() uri = self.document.settings.rep_base_url + self.rep_url % 12 para[:] = [nodes.reference('', rep_type, refuri=uri)] elif name == 'version' and len(body): utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions)
def fig_role(role, rawtext, text, lineno, inliner, options={}, content=[]): text = utils.unescape(text) node = figref('(?)', '(?)', target=text) pending = nodes.pending(FigureReferences) inliner.document.note_pending(pending) return [node], []
def apply(self) -> None: if not Path(self.document["source"]).match("pep-*"): return # not a PEP file, exit early if not len(self.document): raise PEPParsingError("Document tree is empty.") header = self.document[0] if not isinstance( header, nodes.field_list) or "rfc2822" not in header["classes"]: raise PEPParsingError( "Document does not begin with an RFC-2822 header; it is not a PEP." ) # PEP number should be the first field pep_field = header[0] if pep_field[0].astext().lower() != "pep": raise PEPParsingError( "Document does not contain an RFC-2822 'PEP' header!") # Extract PEP number value = pep_field[1].astext() try: pep = int(value) except ValueError: raise PEPParsingError( f"'PEP' header must contain an integer. '{value}' is invalid!") # Special processing for PEP 0. if pep == 0: pending = nodes.pending(pep_zero.PEPZero) self.document.insert(1, pending) self.document.note_pending(pending) # If there are less than two headers in the preamble, or if Title is absent if len(header) < 2 or header[1][0].astext().lower() != "title": raise PEPParsingError("No title!") fields_to_remove = [] for field in header: name = field[0].astext().lower() body = field[1] if len(body) == 0: # body is empty continue elif len(body) > 1: msg = f"PEP header field body contains multiple elements:\n{field.pformat(level=1)}" raise PEPParsingError(msg) elif not isinstance(body[0], nodes.paragraph): # len(body) == 1 msg = f"PEP header field body may only contain a single paragraph:\n{field.pformat(level=1)}" raise PEPParsingError(msg) para = body[0] if name in { "author", "bdfl-delegate", "pep-delegate", "discussions-to", "sponsor" }: # mask emails for node in para: if isinstance(node, nodes.reference): pep_num = pep if name == "discussions-to" else None node.replace_self(_mask_email(node, pep_num)) elif name in {"replaces", "superseded-by", "requires"}: # replace PEP numbers with normalised list of links to PEPs new_body = [] for ref_pep in re.split(r",?\s+", body.astext()): new_body += [ nodes.reference("", ref_pep, refuri=config.pep_url.format( int(ref_pep))) ] new_body += [nodes.Text(", ")] para[:] = new_body[:-1] # drop trailing space elif name in {"last-modified", "content-type", "version"}: # Mark unneeded fields fields_to_remove.append(field) # Remove unneeded fields for field in fields_to_remove: field.parent.remove(field)
def run(self): if len(self.arguments) > 0: try: class_value = directives.class_option(self.arguments[0]) except ValueError: raise self.error( 'Invalid class attribute value for "%s" directive: "%s".' % (self.name, self.arguments[0])) else: class_value = None if 'attributes' in self.options and self.options['attributes'] is not None: try: attributes = [] for attribute in self.options['attributes'].split("\n"): left, sep, right = attribute.partition('=') if sep == '': a_rest_and_key = left a_val = None else: a_rest_and_key = left a_val = right a_list = a_rest_and_key.split(' ') if len(a_list) == 2: a_restriction = a_list[0] a_key = a_list[1] elif len(a_list) == 1: a_restriction = None a_key = a_list[0] else: raise ValueError("wrong format: "+attribute) attributes += [{'key':a_key, 'val':a_val, 'restriction':a_restriction}] except ValueError as e: raise self.error( 'Could not parse attribute string: "%s" (%s)' % (self.options['attributes'], str(e))) attributes = None else: attributes = None node_list = [] if self.content: container = nodes.Element() self.state.nested_parse(self.content, self.content_offset, container) for node in container: if class_value is not None: node['classes'].extend(class_value) if attributes is not None: if 'attributes' in node: node['attributes'].update(attributes) else: node['attributes'] = attributes node_list.extend(container.children) else: pending = nodes.pending( ClassAttribute2, {'class': class_value, 'directive': self.name, 'attributes': attributes}, self.block_text) self.state_machine.document.note_pending(pending) node_list.append(pending) return node_list