def process_stud(app, doctree, fromdocname): env = app.builder.env _keep_report_level = doctree.reporter.report_level info = doctree.reporter.info warn = doctree.reporter.warning doctrees = {} for node in doctree.traverse(stud): source = node.attributes['source'] target_id = _id_prefix + node.attributes['target_id'] if node.attributes['debug']: doctree.reporter.report_level = doctree.reporter.INFO_LEVEL else: doctree.reporter.report_level = _keep_report_level info("stud: studding %s %s" % (source, target_id)) if source not in doctrees: doctrees[source] = _load_source_doctree(env.doctreedir, source, fromdocname) if isa(doctrees[source], WrongSourceDoctree): err = "Unable to find source %s" % source warn(err, line=node.line) replacement = nodes.problematic(err, err) else: new_content = _transclude(doctrees[source], source, target_id, None, info) if new_content is None: err = "Unable to find target %s in source %s" % (target_id, source) warn(err, line=node.line) replacement = nodes.problematic(err, err) elif new_content is []: err = "Empty target %s in source %s" % (target_id, source) warn(err, line=node.line) replacement = [] else: replacement = new_content node.replace_self(replacement) doctree.reporter.report_level = _keep_report_level
def apply(self): if len(self.document.anonymous_refs) \ != len(self.document.anonymous_targets): msg = self.document.reporter.error( 'Anonymous hyperlink mismatch: %s references but %s ' 'targets.\nSee "backrefs" attribute for IDs.' % (len(self.document.anonymous_refs), len(self.document.anonymous_targets))) msgid = self.document.set_id(msg) for ref in self.document.anonymous_refs: prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) return for ref, target in zip(self.document.anonymous_refs, self.document.anonymous_targets): if target.hasattr('refuri'): ref['refuri'] = target['refuri'] ref.resolved = 1 else: ref['refid'] = target['id'] self.document.note_refid(ref) target.referenced = 1
def visit_reference(self, node): if node.resolved or not node.hasattr('refname'): return refname = node['refname'] id = self.document.nameids.get(refname) if id is None: for resolver_function in self.unknown_reference_resolvers: if resolver_function(node): break else: if refname in self.document.nameids: msg = self.document.reporter.error( 'Duplicate target name, cannot be used as a unique ' 'reference: "%s".' % (node['refname']), base_node=node) else: msg = self.document.reporter.error( 'Unknown target name: "%s".' % (node['refname']), base_node=node) msgid = self.document.set_id(msg) prb = nodes.problematic(node.rawsource, node.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) node.replace_self(prb) else: del node['refname'] node['refid'] = id self.document.ids[id].note_referenced_by(id=id) node.resolved = 1
def symbolize_footnotes(self): """Add symbols indexes to "[*]"-style footnotes and references.""" labels = [] for footnote in self.document.symbol_footnotes: reps, index = divmod(self.document.symbol_footnote_start, len(self.symbols)) labeltext = self.symbols[index] * (reps + 1) labels.append(labeltext) footnote.insert(0, nodes.label('', labeltext)) self.document.symbol_footnote_start += 1 self.document.set_id(footnote) i = 0 for ref in self.document.symbol_footnote_refs: try: ref += nodes.Text(labels[i]) except IndexError: msg = self.document.reporter.error( 'Too many symbol footnote references: only %s ' 'corresponding footnotes available.' % len(labels), base_node=ref) msgid = self.document.set_id(msg) for ref in self.document.symbol_footnote_refs[i:]: if ref.resolved or ref.hasattr('refid'): continue prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) break footnote = self.document.symbol_footnotes[i] ref['refid'] = footnote['id'] self.document.note_refid(ref) footnote.add_backref(ref['id']) i += 1
def symbolize_footnotes(self): """Add symbols indexes to "[*]"-style footnotes and references.""" labels = [] for footnote in self.document.symbol_footnotes: reps, index = divmod(self.document.symbol_footnote_start, len(self.symbols)) labeltext = self.symbols[index] * (reps + 1) labels.append(labeltext) footnote.insert(0, nodes.label("", labeltext)) self.document.symbol_footnote_start += 1 self.document.set_id(footnote) i = 0 for ref in self.document.symbol_footnote_refs: try: ref += nodes.Text(labels[i]) except IndexError: msg = self.document.reporter.error( "Too many symbol footnote references: only %s " "corresponding footnotes available." % len(labels), base_node=ref, ) msgid = self.document.set_id(msg) for ref in self.document.symbol_footnote_refs[i:]: if ref.resolved or ref.hasattr("refid"): continue prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) break footnote = self.document.symbol_footnotes[i] assert len(footnote["ids"]) == 1 ref["refid"] = footnote["ids"][0] self.document.note_refid(ref) footnote.add_backref(ref["ids"][0]) i += 1
def report_unknown_code(): if not config["http_strict_mode"]: return [nodes.emphasis(text, text)], [] reporter = document.reporter msg = reporter.error("%d is unknown HTTP status code" % code, line=node.line) prb = nodes.problematic(text, text) return [prb], [msg]
def apply(self): defs = self.document.substitution_defs normed = self.document.substitution_names for refname, refs in self.document.substitution_refs.items(): for ref in refs: key = None if defs.has_key(refname): key = refname else: normed_name = refname.lower() if normed.has_key(normed_name): key = normed[normed_name] if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) else: ref.parent.replace(ref, defs[key].get_children()) self.document.substitution_refs = None # release replaced references
def apply(self): if len(self.document.anonymous_refs) \ != len(self.document.anonymous_targets): msg = self.document.reporter.error( 'Anonymous hyperlink mismatch: %s references but %s ' 'targets.\nSee "backrefs" attribute for IDs.' % (len(self.document.anonymous_refs), len(self.document.anonymous_targets))) msgid = self.document.set_id(msg) for ref in self.document.anonymous_refs: prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) return for ref, target in zip(self.document.anonymous_refs, self.document.anonymous_targets): if target.hasattr('refuri'): ref['refuri'] = target['refuri'] ref.resolved = 1 else: ref['refid'] = target['id'] self.document.note_refid(ref) target.referenced = 1
def problematic(self, text: str, rawsource: str, message: nodes.system_message): msgid = self.document.set_id(message, self.parent) problematic = nodes.problematic(rawsource, rawsource, refid=msgid) prbid = self.document.set_id(problematic) message.add_backref(prbid) return problematic
def number_footnote_references(self, startnum): """Assign numbers to autonumbered footnote references.""" i = 0 for ref in self.document.autofootnote_refs: if ref.resolved or ref.hasattr('refid'): continue try: label = self.autofootnote_labels[i] except IndexError: msg = self.document.reporter.error( 'Too many autonumbered footnote references: only %s ' 'corresponding footnotes available.' % len(self.autofootnote_labels), base_node=ref) msgid = self.document.set_id(msg) for ref in self.document.autofootnote_refs[i:]: if ref.resolved or ref.hasattr('refname'): continue prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) break ref += nodes.Text(label) id = self.document.nameids[label] footnote = self.document.ids[id] ref['refid'] = id self.document.note_refid(ref) assert len(ref['ids']) == 1 footnote.add_backref(ref['ids'][0]) ref.resolved = 1 i += 1
def visit_reference(self, node): if node.resolved or not node.hasattr('refname'): return refname = node['refname'] id = self.document.nameids.get(refname) if id is None: for resolver_function in self.unknown_reference_resolvers: if resolver_function(node): break else: if refname in self.document.nameids: msg = self.document.reporter.error( 'Duplicate target name, cannot be used as a unique ' 'reference: "%s".' % (node['refname']), base_node=node) else: msg = self.document.reporter.error( 'Unknown target name: "%s".' % (node['refname']), base_node=node) msgid = self.document.set_id(msg) prb = nodes.problematic( node.rawsource, node.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) node.replace_self(prb) else: del node['refname'] node['refid'] = id self.document.ids[id].note_referenced_by(id=id) node.resolved = 1
def number_footnote_references(self, startnum): """Assign numbers to autonumbered footnote references.""" i = 0 for ref in self.document.autofootnote_refs: if ref.resolved or ref.hasattr('refid'): continue try: label = self.autofootnote_labels[i] except IndexError: msg = self.document.reporter.error( 'Too many autonumbered footnote references: only %s ' 'corresponding footnotes available.' % len(self.autofootnote_labels), base_node=ref) msgid = self.document.set_id(msg) for ref in self.document.autofootnote_refs[i:]: if ref.resolved or ref.hasattr('refname'): continue prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) break ref += nodes.Text(label) id = self.document.nameids[label] footnote = self.document.ids[id] ref['refid'] = id self.document.note_refid(ref) assert len(ref['ids']) == 1 footnote.add_backref(ref['ids'][0]) ref.resolved = 1 i += 1
def apply(self): defs = self.document.substitution_defs normed = self.document.substitution_names for refname, refs in self.document.substitution_refs.items(): for ref in refs: key = None if defs.has_key(refname): key = refname else: normed_name = refname.lower() if normed.has_key(normed_name): key = normed[normed_name] if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) else: ref.parent.replace(ref, defs[key].get_children()) self.document.substitution_refs = None # release replaced references
def problematic(self, text: str, rawsource: str, message: nodes.system_message) -> nodes.problematic: """Record a system message from parsing.""" msgid = self.document.set_id(message, self.parent) problematic = nodes.problematic(rawsource, text, refid=msgid) prbid = self.document.set_id(problematic) message.add_backref(prbid) return problematic
def report_unknown_code(): if not config['http_strict_mode']: return [nodes.emphasis(text, text)], [] reporter = document.reporter msg = reporter.error('%d is unknown HTTP status code' % code, line=node.line) prb = nodes.problematic(text, text) return [prb], [msg]
def problematic( self, text: str, rawsource: str, message: nodes.system_message ) -> nodes.problematic: """Create a 'problematic' node, if a syntax issue has been encountered.""" msgid = self.document.set_id(message, self.parent) problematic = nodes.problematic(rawsource, text, refid=msgid) prbid = self.document.set_id(problematic) message.add_backref(prbid) return problematic
def process_transclusions(app, doctree, fromdocname): env = app.builder.env #pprint.pprint(env.__dict__) doctrees = {} for node in doctree.traverse(transclude): source = node.attributes['source'] target = node.attributes['target'].lower() if source not in doctrees: doctrees[source] = _load_source_doctree(env, source) if isinstance(doctrees[source], WrongSourceDoctree): err = "Unable to find source %s" % source doctree.reporter.warning(err, line=node.line) node.replace_self(nodes.problematic(err, err)) elif target in doctrees[source].ids: node.replace_self(doctrees[source].ids[target]) else: err = "Unable to find target %s in source %s" % (target, source) doctree.reporter.warning(err, line=node.line) node.replace_self(nodes.problematic(err, err))
def report_invalid_code(): if not config['http_strict_mode']: return [nodes.emphasis(text, text)], [] reporter = document.reporter msg = reporter.error( 'HTTP status code must be an integer (e.g. `200`) or ' 'start with an integer (e.g. `200 OK`); %r is invalid' % text, line=node.line) prb = nodes.problematic(text, text) return [prb], [msg]
def report_invalid_code(): if not config["http_strict_mode"]: return [nodes.emphasis(text, text)], [] reporter = document.reporter msg = reporter.error( "HTTP status code must be an integer (e.g. `200`) or " "start with an integer (e.g. `200 OK`); %r is invalid" % text, line=node.line, ) prb = nodes.problematic(text, text) return [prb], [msg]
def run(self): location = (self.env.docname, self.lineno) args = self.arguments relpath = args[0] abspath, relpath = FindPath(relpath, location) Assert(abspath, "Target not found '{:}'".format(relpath), location) config = self.env.config if config.linkpath_link_github: uri = PathToGithub(relpath, config.linkpath_github_root) else: uri = abspath return [nodes.problematic(text=relpath, refuri=uri)]
def result_nodes(self, document, env, node, is_ref): method = node[0][0].lower() rawsource = node[0].rawsource config = env.domains["http"].env.config if method not in METHOD_REFS: if not config["http_strict_mode"]: return [nodes.emphasis(method, method)], [] reporter = document.reporter msg = reporter.error("%s is not valid HTTP method" % method, line=node.line) prb = nodes.problematic(method, method) return [prb], [msg] url = str(METHOD_REFS[method]) if not url: return [nodes.emphasis(method, method)], [] node = nodes.reference(rawsource, method.upper(), refuri=url) return [node], []
def result_nodes(self, document, env, node, is_ref): method = node[0][0].lower() rawsource = node[0].rawsource config = env.domains['http'].env.config if method not in METHOD_REFS: if not config['http_strict_mode']: return [nodes.emphasis(method, method)], [] reporter = document.reporter msg = reporter.error('%s is not valid HTTP method' % method, line=node.line) prb = nodes.problematic(method, method) return [prb], [msg] url = str(METHOD_REFS[method]) if not url: return [nodes.emphasis(method, method)], [] node = nodes.reference(rawsource, method.upper(), refuri=url) return [node], []
def indirect_target_error(self, target, explanation): naming = '' if target.hasattr('name'): naming = '"%s" ' % target['name'] reflist = self.document.refnames.get(target['name'], []) else: reflist = self.document.refids.get(target['id'], []) naming += '(id="%s")' % target['id'] msg = self.document.reporter.error( 'Indirect hyperlink target %s refers to target "%s", %s.' % (naming, target['refname'], explanation), base_node=target) msgid = self.document.set_id(msg) for ref in reflist: prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) target.resolved = 1
def result_nodes(self, document, env, node, is_ref): header = node[0][0] rawsource = node[0].rawsource config = env.domains["http"].env.config if header not in HEADER_REFS: _header = "-".join(map(lambda i: i.title(), header.split("-"))) if _header not in HEADER_REFS: if not config["http_strict_mode"]: return [nodes.emphasis(header, header)], [] _header = _header.lower() if any([_header.startswith(prefix.lower()) for prefix in config["http_headers_ignore_prefixes"]]): return [nodes.emphasis(header, header)], [] reporter = document.reporter msg = reporter.error("%s is not unknown HTTP header" % header, line=node.line) prb = nodes.problematic(header, header) return [prb], [msg] url = str(HEADER_REFS[header]) node = nodes.reference(rawsource, header, refuri=url) return [node], []
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): try: info = self.data[str(typ)][target] except KeyError: text = contnode.rawsource role = self.roles.get(typ) if role is None: return nodes.emphasis(text, text) resnode = role.result_nodes(env.get_doctree(fromdocname), env, node, None)[0][0] if isinstance(resnode, addnodes.pending_xref): text = node[0][0] reporter = env.get_doctree(fromdocname).reporter reporter.error("Cannot resolve reference to %r" % text, line=node.line) return nodes.problematic(text, text) return resnode else: anchor = http_resource_anchor(typ, target) title = typ.upper() + " " + target return make_refnode(builder, fromdocname, info[0], anchor, contnode, title)
def apply(self): defs = self.document.substitution_defs normed = self.document.substitution_names subreflist = self.document.substitution_refs.items() subreflist.sort() for refname, refs in subreflist: for ref in refs: key = None if defs.has_key(refname): key = refname else: normed_name = refname.lower() if normed.has_key(normed_name): key = normed[normed_name] if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) else: subdef = defs[key] parent = ref.parent index = parent.index(ref) if (subdef.attributes.has_key('ltrim') or subdef.attributes.has_key('trim')): if index > 0 and isinstance(parent[index - 1], nodes.Text): parent.replace(parent[index - 1], parent[index - 1].rstrip()) if (subdef.attributes.has_key('rtrim') or subdef.attributes.has_key('trim')): if (len(parent) > index + 1 and isinstance(parent[index + 1], nodes.Text)): parent.replace(parent[index + 1], parent[index + 1].lstrip()) parent.replace(ref, subdef.children) self.document.substitution_refs = None # release replaced references
def apply(self): defs = self.document.substitution_defs normed = self.document.substitution_names subreflist = self.document.substitution_refs.items() subreflist.sort() for refname, refs in subreflist: for ref in refs: key = None if defs.has_key(refname): key = refname else: normed_name = refname.lower() if normed.has_key(normed_name): key = normed[normed_name] if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) else: subdef = defs[key] parent = ref.parent index = parent.index(ref) if (subdef.attributes.has_key('ltrim') or subdef.attributes.has_key('trim')): if index > 0 and isinstance(parent[index - 1], nodes.Text): parent.replace(parent[index - 1], parent[index - 1].rstrip()) if (subdef.attributes.has_key('rtrim') or subdef.attributes.has_key('trim')): if (len(parent) > index + 1 and isinstance(parent[index + 1], nodes.Text)): parent.replace(parent[index + 1], parent[index + 1].lstrip()) parent.replace(ref, subdef.children) self.document.substitution_refs = None # release replaced references
def visit_reference(self, node): if node.resolved or not node.hasattr('refname'): return refname = node['refname'] id = self.document.nameids.get(refname) if id is None: msg = self.document.reporter.error( 'Unknown target name: "%s".' % (node['refname']), base_node=node) msgid = self.document.set_id(msg) prb = nodes.problematic( node.rawsource, node.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) node.parent.replace(node, prb) else: del node['refname'] node['refid'] = id self.document.ids[id].referenced = 1 node.resolved = 1
def indirect_target_error(self, target, explanation): naming = '' if target.hasattr('name'): naming = '"%s" ' % target['name'] reflist = self.document.refnames.get(target['name'], []) else: reflist = self.document.refids.get(target['id'], []) naming += '(id="%s")' % target['id'] msg = self.document.reporter.error( 'Indirect hyperlink target %s refers to target "%s", %s.' % (naming, target['refname'], explanation), base_node=target) msgid = self.document.set_id(msg) for ref in reflist: prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) target.resolved = 1
def visit_reference(self, node): if node.resolved or not node.hasattr('refname'): return refname = node['refname'] id = self.document.nameids.get(refname) if id is None: msg = self.document.reporter.error('Unknown target name: "%s".' % (node['refname']), base_node=node) msgid = self.document.set_id(msg) prb = nodes.problematic(node.rawsource, node.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) node.parent.replace(node, prb) else: del node['refname'] node['refid'] = id self.document.ids[id].referenced = 1 node.resolved = 1
def widgetbrowser_directive(dirname, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Processes the `widgetbrowser` reStructuredText directive. When generating the URL for the widget it peeks into os.environ for the 'TW_BROWSER_PREFIX' environment variable. """ widget_path = arguments[0] widget = util.import_widget(widget_path) if not widget: reporter = state.document.reporter msg = reporter.warning( 'No widget found at %r' % widget_path, line=lineno) prb = nodes.problematic(block_text, block_text, msg) return [msg, prb] tabs = options.get('tabs') or widget_tabs.tabs prefix = os.environ.get('TW_BROWSER_PREFIX', '/apps/docs') size = options.get('size') html = widget_tabs(widget, tabs=tabs, prefix=prefix, size=size) node = nodes.raw('', html, format='html') return [node]
def indirect_target_error(self, target, explanation): naming = '' reflist = [] if target['names']: naming = '"%s" ' % target['names'][0] for name in target['names']: reflist.extend(self.document.refnames.get(name, [])) for id in target['ids']: reflist.extend(self.document.refids.get(id, [])) naming += '(id="%s")' % target['ids'][0] msg = self.document.reporter.error( 'Indirect hyperlink target %s refers to target "%s", %s.' % (naming, target['refname'], explanation), base_node=target) msgid = self.document.set_id(msg) for ref in utils.uniq(reflist): prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) target.resolved = 1
def indirect_target_error(self, target, explanation): naming = '' reflist = [] if target['names']: naming = '"%s" ' % target['names'][0] for name in target['names']: reflist.extend(self.document.refnames.get(name, [])) for id in target['ids']: reflist.extend(self.document.refids.get(id, [])) naming += '(id="%s")' % target['ids'][0] msg = self.document.reporter.error( 'Indirect hyperlink target %s refers to target "%s", %s.' % (naming, target['refname'], explanation), base_node=target) msgid = self.document.set_id(msg) for ref in utils.uniq(reflist): prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) target.resolved = 1
def __report(self, level, node, error, *args): msg = str(error(*args)) sysmsg = self.document.reporter.system_message #if node: # msgnode = sysmsg(level, msg, node) msgnode = sysmsg(level, msg) prbid = 'unknown' if node and len(node)>=2 and len(node[1]): node = node[1][0] msgid = self.document.set_id(msgnode) # XXX: include problematic/invalid values or not.. prb = nodes.problematic('',node.astext(), refid=msgid) prbid = self.document.set_id(prb) msgnode.add_backref(prbid) node.replace_self(prb) #prb += node logger.info('Reported %s: %s, %s', level, error, prbid) self.messages.append(msgnode) return msgnode
def apply(self): anonymous_refs = [] anonymous_targets = [] for node in self.document.traverse(nodes.reference): if node.get('anonymous'): anonymous_refs.append(node) for node in self.document.traverse(nodes.target): if node.get('anonymous'): anonymous_targets.append(node) if len(anonymous_refs) \ != len(anonymous_targets): msg = self.document.reporter.error( 'Anonymous hyperlink mismatch: %s references but %s ' 'targets.\nSee "backrefs" attribute for IDs.' % (len(anonymous_refs), len(anonymous_targets))) msgid = self.document.set_id(msg) for ref in anonymous_refs: prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) return for ref, target in zip(anonymous_refs, anonymous_targets): target.referenced = 1 while 1: if target.hasattr('refuri'): ref['refuri'] = target['refuri'] ref.resolved = 1 break else: if not target['ids']: # Propagated target. target = self.document.ids[target['refid']] continue ref['refid'] = target['ids'][0] self.document.note_refid(ref) break
def apply(self): anonymous_refs = [] anonymous_targets = [] for node in self.document.traverse(nodes.reference): if node.get('anonymous'): anonymous_refs.append(node) for node in self.document.traverse(nodes.target): if node.get('anonymous'): anonymous_targets.append(node) if len(anonymous_refs) \ != len(anonymous_targets): msg = self.document.reporter.error( 'Anonymous hyperlink mismatch: %s references but %s ' 'targets.\nSee "backrefs" attribute for IDs.' % (len(anonymous_refs), len(anonymous_targets))) msgid = self.document.set_id(msg) for ref in anonymous_refs: prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) return for ref, target in zip(anonymous_refs, anonymous_targets): target.referenced = 1 while True: if target.hasattr('refuri'): ref['refuri'] = target['refuri'] ref.resolved = 1 break else: if not target['ids']: # Propagated target. target = self.document.ids[target['refid']] continue ref['refid'] = target['ids'][0] self.document.note_refid(ref) break
def apply(self): if len(self.document.anonymous_refs) \ != len(self.document.anonymous_targets): msg = self.document.reporter.error( 'Anonymous hyperlink mismatch: %s references but %s ' 'targets.\nSee "backrefs" attribute for IDs.' % (len(self.document.anonymous_refs), len(self.document.anonymous_targets))) msgid = self.document.set_id(msg) for ref in self.document.anonymous_refs: prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) for target in self.document.anonymous_targets: # Assume that all anonymous targets have been # referenced to avoid generating lots of # system_messages. target.referenced = 1 return for ref, target in zip(self.document.anonymous_refs, self.document.anonymous_targets): target.referenced = 1 while 1: if target.hasattr('refuri'): ref['refuri'] = target['refuri'] ref.resolved = 1 break else: if not target['ids']: # Propagated target. target = self.document.ids[target['refid']] continue ref['refid'] = target['ids'][0] self.document.note_refid(ref) break
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): try: info = self.data[str(typ)][target] except KeyError: text = contnode.rawsource role = self.roles.get(typ) if role is None: return nodes.emphasis(text, text) resnode = role.result_nodes(env.get_doctree(fromdocname), env, node, None)[0][0] if isinstance(resnode, addnodes.pending_xref): text = node[0][0] reporter = env.get_doctree(fromdocname).reporter reporter.error('Cannot resolve reference to %r' % text, line=node.line) return nodes.problematic(text, text) return resnode else: anchor = http_resource_anchor(typ, target) title = typ.upper() + ' ' + target return make_refnode(builder, fromdocname, info[0], anchor, contnode, title)
def result_nodes(self, document, env, node, is_ref): header = node[0][0] rawsource = node[0].rawsource config = env.domains['http'].env.config if header not in HEADER_REFS: _header = '-'.join(map(lambda i: i.title(), header.split('-'))) if _header not in HEADER_REFS: if not config['http_strict_mode']: return [nodes.emphasis(header, header)], [] _header = _header.lower() if any([ _header.startswith(prefix.lower()) for prefix in config['http_headers_ignore_prefixes'] ]): return [nodes.emphasis(header, header)], [] reporter = document.reporter msg = reporter.error('%s is not unknown HTTP header' % header, line=node.line) prb = nodes.problematic(header, header) return [prb], [msg] url = str(HEADER_REFS[header]) node = nodes.reference(rawsource, header, refuri=url) return [node], []
def apply(self): if len(self.document.anonymous_refs) \ != len(self.document.anonymous_targets): msg = self.document.reporter.error( 'Anonymous hyperlink mismatch: %s references but %s ' 'targets.\nSee "backrefs" attribute for IDs.' % (len(self.document.anonymous_refs), len(self.document.anonymous_targets))) msgid = self.document.set_id(msg) for ref in self.document.anonymous_refs: prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.parent.replace(ref, prb) for target in self.document.anonymous_targets: # Assume that all anonymous targets have been # referenced to avoid generating lots of # system_messages. target.referenced = 1 return for ref, target in zip(self.document.anonymous_refs, self.document.anonymous_targets): target.referenced = 1 while 1: if target.hasattr('refuri'): ref['refuri'] = target['refuri'] ref.resolved = 1 break else: if not target['ids']: # Propagated target. target = self.document.ids[target['refid']] continue ref['refid'] = target['ids'][0] self.document.note_refid(ref) break
def apply(self): defs = self.document.substitution_defs normed = self.document.substitution_names subreflist = self.document.traverse(nodes.substitution_reference) nested = {} for ref in subreflist: refname = ref['refname'] key = None if refname in defs: key = refname else: normed_name = refname.lower() if normed_name in normed: key = normed[normed_name] if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) else: subdef = defs[key] parent = ref.parent index = parent.index(ref) if ('ltrim' in subdef.attributes or 'trim' in subdef.attributes): if index > 0 and isinstance(parent[index - 1], nodes.Text): parent.replace(parent[index - 1], parent[index - 1].rstrip()) if ('rtrim' in subdef.attributes or 'trim' in subdef.attributes): if (len(parent) > index + 1 and isinstance(parent[index + 1], nodes.Text)): parent.replace(parent[index + 1], parent[index + 1].lstrip()) subdef_copy = subdef.deepcopy() try: # Take care of nested substitution references: for nested_ref in subdef_copy.traverse( nodes.substitution_reference): nested_name = normed[nested_ref['refname'].lower()] if nested_name in nested.setdefault(nested_name, []): raise CircularSubstitutionDefinitionError else: nested[nested_name].append(key) subreflist.append(nested_ref) except CircularSubstitutionDefinitionError: parent = ref.parent if isinstance(parent, nodes.substitution_definition): msg = self.document.reporter.error( 'Circular substitution definition detected:', nodes.literal_block(parent.rawsource, parent.rawsource), line=parent.line, base_node=parent) parent.replace_self(msg) else: msg = self.document.reporter.error( 'Circular substitution definition referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) else: ref.replace_self(subdef_copy.children) # register refname of the replacment node(s) # (needed for resolution of references) for node in subdef_copy.children: if isinstance(node, nodes.Referential): # HACK: verify refname attribute exists. # Test with docs/dev/todo.txt, see. |donate| if 'refname' in node: self.document.note_refname(node)
def apply(self): defs = self.document.substitution_defs normed = self.document.substitution_names nested = {} line_length_limit = getattr(self.document.settings, "line_length_limit", 10000) subreflist = list(self.document.traverse(nodes.substitution_reference)) for ref in subreflist: msg = '' refname = ref['refname'] if refname in defs: key = refname else: normed_name = refname.lower() key = normed.get(normed_name, None) if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) else: subdef = defs[key] if len(subdef.astext()) > line_length_limit: msg = self.document.reporter.error( 'Substitution definition "%s" exceeds the' ' line-length-limit.' % (key)) if msg: msgid = self.document.set_id(msg) prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) continue parent = ref.parent index = parent.index(ref) if ('ltrim' in subdef.attributes or 'trim' in subdef.attributes): if index > 0 and isinstance(parent[index - 1], nodes.Text): parent[index - 1] = parent[index - 1].rstrip() if ('rtrim' in subdef.attributes or 'trim' in subdef.attributes): if (len(parent) > index + 1 and isinstance(parent[index + 1], nodes.Text)): parent[index + 1] = parent[index + 1].lstrip() subdef_copy = subdef.deepcopy() try: # Take care of nested substitution references: for nested_ref in subdef_copy.traverse( nodes.substitution_reference): nested_name = normed[nested_ref['refname'].lower()] if nested_name in nested.setdefault(nested_name, []): raise CircularSubstitutionDefinitionError nested[nested_name].append(key) nested_ref['ref-origin'] = ref subreflist.append(nested_ref) except CircularSubstitutionDefinitionError: parent = ref.parent if isinstance(parent, nodes.substitution_definition): msg = self.document.reporter.error( 'Circular substitution definition detected:', nodes.literal_block(parent.rawsource, parent.rawsource), line=parent.line, base_node=parent) parent.replace_self(msg) else: # find original ref substitution which caused this error ref_origin = ref while ref_origin.hasattr('ref-origin'): ref_origin = ref_origin['ref-origin'] msg = self.document.reporter.error( 'Circular substitution definition referenced: ' '"%s".' % refname, base_node=ref_origin) msgid = self.document.set_id(msg) prb = nodes.problematic(ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) continue ref.replace_self(subdef_copy.children) # register refname of the replacment node(s) # (needed for resolution of references) for node in subdef_copy.children: if isinstance(node, nodes.Referential): # HACK: verify refname attribute exists. # Test with docs/dev/todo.txt, see. |donate| if 'refname' in node: self.document.note_refname(node)
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.parent.replace(node, mask_email(node)) elif name == "discussions-to": for node in para: if isinstance(node, nodes.reference): node.parent.replace(node, mask_email(node, pep)) elif name in ("replaces", "replaced-by", "requires"): newbody = [] space = nodes.Text(" ") for refpep in re.split(",?\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): 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): defs = self.document.substitution_defs normed = self.document.substitution_names subreflist = self.document.traverse(nodes.substitution_reference) nested = {} for ref in subreflist: refname = ref['refname'] key = None if defs.has_key(refname): key = refname else: normed_name = refname.lower() if normed.has_key(normed_name): key = normed[normed_name] if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) else: subdef = defs[key] parent = ref.parent index = parent.index(ref) if (subdef.attributes.has_key('ltrim') or subdef.attributes.has_key('trim')): if index > 0 and isinstance(parent[index - 1], nodes.Text): parent.replace(parent[index - 1], parent[index - 1].rstrip()) if (subdef.attributes.has_key('rtrim') or subdef.attributes.has_key('trim')): if (len(parent) > index + 1 and isinstance(parent[index + 1], nodes.Text)): parent.replace(parent[index + 1], parent[index + 1].lstrip()) subdef_copy = subdef.deepcopy() try: # Take care of nested substitution references: for nested_ref in subdef_copy.traverse( nodes.substitution_reference): nested_name = normed[nested_ref['refname'].lower()] if nested_name in nested.setdefault(nested_name, []): raise CircularSubstitutionDefinitionError else: nested[nested_name].append(key) subreflist.append(nested_ref) except CircularSubstitutionDefinitionError: parent = ref.parent if isinstance(parent, nodes.substitution_definition): msg = self.document.reporter.error( 'Circular substitution definition detected:', nodes.literal_block(parent.rawsource, parent.rawsource), line=parent.line, base_node=parent) parent.replace_self(msg) else: msg = self.document.reporter.error( 'Circular substitution definition referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) else: ref.replace_self(subdef_copy.children)
def problematic(self, text, rawsource, message): msgid = self.document.set_id(message, self.parent) problematic = nodes.problematic(rawsource, text, refid=msgid) prbid = self.document.set_id(problematic) message.add_backref(prbid) return problematic
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 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 apply(self): defs = self.document.substitution_defs normed = self.document.substitution_names subreflist = self.document.traverse(nodes.substitution_reference) nested = {} for ref in subreflist: refname = ref['refname'] key = None if refname in defs: key = refname else: normed_name = refname.lower() if normed_name in normed: key = normed[normed_name] if key is None: msg = self.document.reporter.error( 'Undefined substitution referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) else: subdef = defs[key] parent = ref.parent index = parent.index(ref) if ('ltrim' in subdef.attributes or 'trim' in subdef.attributes): if index > 0 and isinstance(parent[index - 1], nodes.Text): parent.replace(parent[index - 1], parent[index - 1].rstrip()) if ('rtrim' in subdef.attributes or 'trim' in subdef.attributes): if (len(parent) > index + 1 and isinstance(parent[index + 1], nodes.Text)): parent.replace(parent[index + 1], parent[index + 1].lstrip()) subdef_copy = subdef.deepcopy() try: # Take care of nested substitution references: for nested_ref in subdef_copy.traverse( nodes.substitution_reference): nested_name = normed[nested_ref['refname'].lower()] if nested_name in nested.setdefault(nested_name, []): raise CircularSubstitutionDefinitionError else: nested[nested_name].append(key) subreflist.append(nested_ref) except CircularSubstitutionDefinitionError: parent = ref.parent if isinstance(parent, nodes.substitution_definition): msg = self.document.reporter.error( 'Circular substitution definition detected:', nodes.literal_block(parent.rawsource, parent.rawsource), line=parent.line, base_node=parent) parent.replace_self(msg) else: msg = self.document.reporter.error( 'Circular substitution definition referenced: "%s".' % refname, base_node=ref) msgid = self.document.set_id(msg) prb = nodes.problematic( ref.rawsource, ref.rawsource, refid=msgid) prbid = self.document.set_id(prb) msg.add_backref(prbid) ref.replace_self(prb) else: ref.replace_self(subdef_copy.children) # register refname of the replacment node(s) # (needed for resolution of references) for node in subdef_copy.children: if isinstance(node, nodes.Referential): # HACK: verify refname attribute exists. # Test with docs/dev/todo.txt, see. |donate| if 'refname' in node: self.document.note_refname(node)