def make_content(self, all_members): doc = self.item content = addnodes.desc_content() if doc.exports or doc.dependencies: with addto(content, nodes.field_list()) as fields: if doc.exports: with addto(fields, nodes.field()) as field: field += nodes.field_name('Exports', 'Exports') with addto(field, nodes.field_body()) as body: ref = doc['exports'] # warning: not the same as doc.exports label = ref or '<anonymous>' link = addnodes.pending_xref( ref, nodes.paragraph(ref, label), refdomain='js', reftype='any', reftarget=ref, ) link['js:module'] = doc.name body += link if doc.dependencies: with addto(fields, nodes.field()) as field: self.make_dependencies(field, doc) if doc.doc: # FIXME: source offset self.directive.state.nested_parse(to_list(doc.doc, source=doc['sourcefile']), 0, content) self.directive.state.nested_parse(self.directive.content, 0, content) content += self.document_properties(all_members) return content
def _build_markup(self): field_list = nodes.field_list() item = nodes.paragraph() item.append(field_list) if 'branch' in self.options: name = nodes.field_name(text="Branch") body = nodes.field_body() body.append(nodes.emphasis(text=self.branch_name)) field = nodes.field() field += [name, body] field_list.append(field) if 'commit' in self.options: name = nodes.field_name(text="Commit") body = nodes.field_body() if 'no_github_link' in self.options: body.append(self._commit_text_node()) else: body.append(self._github_link()) field = nodes.field() field += [name, body] field_list.append(field) if 'uncommitted' in self.options and self.repo.is_dirty(): item.append(nodes.warning('', nodes.inline( text="There were uncommitted changes when this was compiled." ))) if 'untracked' in self.options and self.repo.untracked_files: item.append(nodes.warning('', nodes.inline( text="There were untracked files when this was compiled." ))) return [item]
def make_content(self, all_members): ret = nodes.section() doc = self.item if doc.doc: self.directive.state.nested_parse(to_list(doc.doc), 0, ret) check_parameters(self, doc) params, subtypes = extract_subtypes(self.item.name, self.item) rdoc = doc.return_val.doc rtype = doc.return_val.type if params or rtype or rdoc: with addto(ret, nodes.field_list()) as fields: if params: with addto(fields, nodes.field()) as field: field += nodes.field_name('Parameters', 'Parameters') with addto(field, nodes.field_body()) as body,\ addto(body, nodes.bullet_list()) as holder: holder.extend(make_parameters(params, mod=doc['sourcemodule'].name)) if rdoc: with addto(fields, nodes.field()) as field: field += nodes.field_name("Returns", "Returns") with addto(field, nodes.field_body()) as body,\ addto(body, nodes.paragraph()) as p: p += nodes.inline(rdoc, rdoc) if rtype: with addto(fields, nodes.field()) as field: field += nodes.field_name("Return Type", "Return Type") with addto(field, nodes.field_body()) as body, \ addto(body, nodes.paragraph()) as p: p += make_types(rtype, mod=doc['sourcemodule'].name) ret += self.document_subtypes(subtypes) return ret.children
def run(self): self.cabal_meta = self.get_meta() result = super(CabalObject, self).run() if self.cabal_meta.since is not None \ or self.cabal_meta.deprecated is not None: #find content part of description for item in result: if isinstance(item, addnodes.desc): desc = item break else: return result for item in desc: if isinstance(item, addnodes.desc_content): contents = item break else: return result # find exsting field list and add to it # or create new one for item in contents: if isinstance(item, nodes.field_list): field_list = item break else: field_list = nodes.field_list('') contents.insert(0, field_list) if self.cabal_meta.since is not None: #docutils horror field = nodes.field('') field_name = nodes.field_name('Since', 'Since') since = 'Cabal ' + str(self.cabal_meta.since) field_body = nodes.field_body(since, nodes.paragraph(since, since)) field += field_name field += field_body field_list.insert(0, field) if self.cabal_meta.deprecated is not None: field = nodes.field('') field_name = nodes.field_name('Deprecated', 'Deprecated') if isinstance(self.cabal_meta.deprecated, StrictVersion): since = 'Cabal ' + str(self.cabal_meta.deprecated) else: since = '' field_body = nodes.field_body(since, nodes.paragraph(since, since)) field += field_name field += field_body field_list.insert(0, field) return result
def handle_doc_fields(node): # don't traverse, only handle field lists that are immediate children for child in node.children: if not isinstance(child, nodes.field_list): continue params = None param_nodes = {} param_types = {} new_list = nodes.field_list() for field in child: fname, fbody = field try: typ, obj = fname.astext().split(None, 1) typ = doc_fields_with_arg[typ] if len(fbody.children) == 1 and \ isinstance(fbody.children[0], nodes.paragraph): children = fbody.children[0].children else: children = fbody.children if typ == 'param': if not params: pfield = nodes.field() pfield += nodes.field_name('Parameters', 'Parameters') pfield += nodes.field_body() params = nodes.bullet_list() pfield[1] += params new_list += pfield dlitem = nodes.list_item() dlpar = nodes.paragraph() dlpar += nodes.emphasis(obj, obj) dlpar += nodes.Text(' -- ', ' -- ') dlpar += children param_nodes[obj] = dlpar dlitem += dlpar params += dlitem elif typ == 'type': param_types[obj] = fbody.astext() else: fieldname = typ + ' ' + obj nfield = nodes.field() nfield += nodes.field_name(fieldname, fieldname) nfield += nodes.field_body() nfield[1] += fbody.children new_list += nfield except (KeyError, ValueError): fnametext = fname.astext() try: typ = doc_fields_without_arg[fnametext] except KeyError: # at least capitalize the field name typ = fnametext.capitalize() fname[0] = nodes.Text(typ) new_list += field for param, type in param_types.iteritems(): if param in param_nodes: param_nodes[param].insert(1, nodes.Text(' (%s)' % type)) child.replace_self(new_list)
def make_field(self, types, domain, items): fieldname = nodes.field_name("", self.label) listnode = self.list_type() for fieldarg, content in items: par = nodes.paragraph() par += self.make_xref(self.rolename, domain, fieldarg, addnodes.literal_strong) par += nodes.Text(" -- ") par += content listnode += nodes.list_item("", par) if len(items) == 1 and self.can_collapse: fieldbody = nodes.field_body("", listnode[0][0]) return nodes.field("", fieldname, fieldbody) fieldbody = nodes.field_body("", listnode) return nodes.field("", fieldname, fieldbody)
def make_field(self, types, domain, items): def handle_item(fieldarg, content): par = nodes.paragraph() par.extend(self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong)) if fieldarg in types: par += nodes.Text(' (') # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = u''.join(n.astext() for n in fieldtype) par.extend(self.make_xrefs(self.typerolename, domain, typename, addnodes.literal_emphasis)) else: par += fieldtype par += nodes.Text(')') par += nodes.Text(' -- ') par += content return par fieldname = nodes.field_name('', self.label) if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode = handle_item(fieldarg, content) else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item('', handle_item(fieldarg, content)) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def run(self): try: fields = self.future_fields.get(timeout=30) except Queue.Empty: return [self.state_machine.reporter.error( "Timed out while fetching fields related to action [%s]" % self.arguments[0] )] if fields is None: return [self.state_machine.reporter.warning( "Could not find any field related to the action [%s]" % self.arguments[0] )] whitelist = set(self.options.get('only', '').split()) return [nodes.field_list('', *( nodes.field('', nodes.field_name(text=v['string'] or k), nodes.field_body('', # keep help formatting around (e.g. newlines for lists) nodes.line_block('', *( nodes.line(text=line) for line in v['help'].split('\n') )) ) ) for k, v in fields.iteritems() # if there's a whitelist, only display whitelisted fields if not whitelist or k in whitelist # only display if there's a help text if v.get('help') ))]
def make_field(self, name, body): if not isinstance(body, nodes.Node): body = nodes.paragraph(text=body) return nodes.field( '', nodes.field_name(text=name), nodes.field_body('', body))
def make_field(self, types, domain, items): fieldname = nodes.field_name('', self.label) listnode = self.list_type() for fieldarg, content in items: listnode += nodes.list_item('', nodes.paragraph('', '', *content)) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def make_field(self, field_name, field_body): """Fill content into nodes. :param string field_name: Field name of the field :param field_name: Field body if the field :type field_name: str or instance of docutils.nodes :return: field instance filled with given name and body :rtype: nodes.field """ name = nodes.field_name() name += nodes.Text(field_name) paragraph = nodes.paragraph() if isinstance(field_body, six.string_types): # This is the case when field_body is just a string: paragraph += nodes.Text(field_body) else: # This is the case when field_body is a complex node: # useful when constructing nested field lists paragraph += field_body body = nodes.field_body() body += paragraph field = nodes.field() field.extend([name, body]) return field
def process_motor_nodes(app, doctree): # Search doctree for Motor's methods and attributes whose docstrings were # copied from PyMongo, and fix them up for Motor: # 1. Add a 'callback' param (sometimes optional, sometimes required) to # all async methods. If the PyMongo method took no params, we create # a parameter-list from scratch, otherwise we edit PyMongo's list. # 2. Remove all version annotations like "New in version 2.0" since # PyMongo's version numbers are meaningless in Motor's docs. # 3. Remove "seealso" directives that reference PyMongo's docs. # # We do this here, rather than by registering a callback to Sphinx's # 'autodoc-process-signature' event, because it's way easier to handle the # parsed doctree before it's turned into HTML than it is to update the RST. for objnode in doctree.traverse(desc): if objnode["objtype"] in ("method", "attribute"): signature_node = find_by_path(objnode, [desc_signature])[0] name = ".".join([signature_node["module"], signature_node["fullname"]]) assert name.startswith("motor.") obj_motor_info = motor_info.get(name) if obj_motor_info: desc_content_node = find_by_path(objnode, [desc_content])[0] if obj_motor_info.get("is_async_method"): try: # Find the parameter list, a bullet_list instance parameters_node = find_by_path(desc_content_node, [field_list, field, field_body, bullet_list])[ 0 ] except IndexError: # PyMongo method has no parameters, create an empty # params list parameters_node = bullet_list() parameters_field_list_node = field_list( "", field("", field_name("", "Parameters "), field_body("", parameters_node)) ) desc_content_node.append(parameters_field_list_node) insert_callback(parameters_node) callback_future_text = "If a callback is passed, returns None, else returns a" " Future." desc_content_node.append(paragraph("", Text(callback_future_text))) if obj_motor_info["is_pymongo_docstring"]: # Remove all "versionadded", "versionchanged" and # "deprecated" directives from the docs we imported from # PyMongo version_nodes = find_by_path(desc_content_node, [versionmodified]) for version_node in version_nodes: version_node.parent.remove(version_node) # Remove all "seealso" directives that contain :doc: # references from PyMongo's docs seealso_nodes = find_by_path(desc_content_node, [seealso]) for seealso_node in seealso_nodes: if 'reftype="doc"' in str(seealso_node): seealso_node.parent.remove(seealso_node)
def make_field(self, types, domain, item): fieldarg, content = item fieldname = nodes.field_name("", self.label) if fieldarg: fieldname += nodes.Text(" ") fieldname += self.make_xref(self.rolename, domain, fieldarg, nodes.Text) fieldbody = nodes.field_body("", nodes.paragraph("", "", *content)) return nodes.field("", fieldname, fieldbody)
def bullet_list_field(key, value): items = [] for item in value: item_p = nodes.paragraph(item, item) items.append(nodes.list_item('', item_p)) bullet_list = nodes.bullet_list('', *items) field_name = nodes.field_name(key, key) field_body = nodes.field_body('', bullet_list) return nodes.field('', field_name, field_body)
def make_field(self, types, domain, items): # type: (List, unicode, Tuple) -> nodes.field fieldname = nodes.field_name('', self.label) listnode = self.list_type() for fieldarg, content in items: par = nodes.paragraph() par.extend(self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong)) par += nodes.Text(' -- ') par += content listnode += nodes.list_item('', par) if len(items) == 1 and self.can_collapse: fieldbody = nodes.field_body('', listnode[0][0]) return nodes.field('', fieldname, fieldbody) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def make_field(self, domain, items): fieldname = nodes.field_name('', self.label) listnode = self.list_type() for content in items: par = nodes.paragraph() par += content listnode += nodes.list_item('', par) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def make_params(self, params): if not params: return [] ret = nodes.field('', nodes.field_name('Parameters', 'Parameters')) with addto(ret, nodes.field_body()) as body,\ addto(body, nodes.bullet_list()) as holder: holder += make_parameters(params, mod=self.modname) return ret
def _parse(self, tree): if isinstance(tree, minidom.Document): return self._parse(tree.childNodes[0]) if isinstance(tree, minidom.Text): return nodes.Text(tree.data) # Get children. children = [self._parse(c) for c in tree.childNodes] if tree.tagName == 'epytext': return children if tree.tagName == 'para': return nodes.paragraph('','', *children) if tree.tagName == 'section': return nodes.section('', *children) if tree.tagName == 'heading': return nodes.title('','', *children) if tree.tagName == 'fieldlist': return nodes.field_list('', *children) if tree.tagName == 'field': return nodes.field('', *self._parse_field(tree, children)) if tree.tagName == 'literalblock': return nodes.literal_block('','', *children) if tree.tagName == 'doctestblock': return nodes.doctest_block('','', *children) if tree.tagName == 'ulist': return nodes.bullet_list('', *children) if tree.tagName == 'olist': return nodes.enumerated_list('', *children) if tree.tagName == 'li': return nodes.list_item('', *children) if tree.tagName == 'link': # [XX] discards link target. name, target = children return nodes.title_reference('','', name) if tree.tagName == 'uri': name, target = children return nodes.reference('','', name, refuid=target.astext()) if tree.tagName == 'code': return nodes.literal('','', *children) if tree.tagName == 'math': return nodes.emphasis('','', *children) if tree.tagName == 'italic': return nodes.emphasis('','', *children) if tree.tagName == 'bold': return nodes.strong('','', *children) if tree.tagName == 'indexed': # [XX] doesn't mark the fact that it's indexedd return nodes.emphasis('','', *children) if tree.tagName == 'symbol': # use substitutions. # [XX] this needs to be fixed! return nodes.Text(children[0]) elif tree.tagName in ('tag', 'arg', 'name', 'target'): return children[0] else: raise ValueError, ('unknown %s' % tree.tagName)
def fieldlist(fields, *classes): node = nodes.field_list('') node['classes'].extend(classes) for name, value in fields: node += nodes.field('', nodes.field_name('', name), nodes.field_body('', nodes.paragraph('', value)), ) return node
def make_field(self, types, domain, items, **kwargs): fieldname = nodes.field_name('', self.label) #par = Field.make_field(self, types, domain, items[0]) par = nodes.paragraph() for i,item in enumerate(items): if i: par += nodes.Text(' ') par += item[1]#Field.make_field(self, types, domain, item) fieldbody = nodes.field_body('', par) return nodes.field('', fieldname, fieldbody)
def make_field(self, tag, value): field = nodes.field() field.append(nodes.field_name(text=tag)) body = nodes.field_body() if isinstance(value, basestring): body.append(sphinx.addnodes.compact_paragraph(text=value)) else: body.append(value) field.append(body) return field
def make_field(self, types, domain, items, env=None): fieldname = nodes.field_name('', self.label) listnode = self.list_type() if len(items) == 1 and self.can_collapse: return Field.make_field(self, types, domain, items[0]) for fieldarg, content in items: par = nodes.paragraph() par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong) listnode += nodes.list_item('', par) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, items): fieldname = nodes.field_name('', self.label) if len(items) == 1 and self.can_collapse: return Field.make_field(self, types, domain, items[0]) bodynode = nodes.paragraph() for i, (fieldarg, content) in enumerate(items): bodynode += nodes.Text(', ') if i else None bodynode += self.make_xref(self.bodyrolename, domain, content[0].astext(), nodes.Text) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, items): if len(items) == 1 and self.can_collapse: super(NoArgGroupedField, self).make_field(types, domain, items) fieldname = nodes.field_name("", self.label) listnode = self.list_type() for fieldarg, content in items: par = nodes.paragraph() par += content listnode += nodes.list_item("", par) fieldbody = nodes.field_body("", listnode) return nodes.field("", fieldname, fieldbody)
def make_field(self, types, domain, item, env=None): fieldname = nodes.field_name('', self.label) backref = addnodes.pending_xref( '', refdomain="conda", reftype='requiredby', refexplicit=False, reftarget=env.ref_context['conda:package'], refdoc=env.docname) backref += nodes.inline('', '') fieldbody = nodes.field_body('', backref) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, items, env=None): fieldname = nodes.field_name('', self.label) listnode = self.list_type() for fieldarg, content in items: par = nodes.paragraph() par.extend( self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong, env=env)) par += nodes.Text(' -- ') par += content listnode += nodes.list_item('', par) if len(items) == 1 and self.can_collapse: fieldbody = nodes.field_body('', listnode[0][0]) return nodes.field('', fieldname, fieldbody) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def construct_property_description_list(name): """ Construct a skeleton for sphinx member description block """ description_group_list = nodes.field_list() obj_desc = nodes.field() obj_desc += nodes.field_name(_(name), _(name)) description_group_list += obj_desc obj_list = nodes.bullet_list() description_group_list += nodes.field_body('', obj_list) return description_group_list, obj_list
def run(self): field_list = nodes.field_list() for name, value in TAGS: fieldname = nodes.field_name() fieldname += nodes.Text(name) fieldbody = nodes.field_body() para = nodes.paragraph() para += nodes.Text(value) fieldbody += para field = nodes.field('', fieldname, fieldbody) field_list += field return [field_list]
def make_field(self, directive): # treat content like docfields.Field value = directive.options.get(self.name) if value: name = nodes.field_name('', self.label) para = nodes.paragraph(rawsource=value) content = ViewList() content.append(value, *directive.content.items[0]) directive.state.nested_parse(content, directive.content_offset, para) body = nodes.field_body('', para) return nodes.field('', name, body)
def _raw_fields(self, data, field_name=''): body = nodes.field_body() if isinstance(data, list): for item in data: body.append(self._raw_html_block(data=item)) else: body.append(self._raw_html_block(data=data)) field = nodes.field() field.append(nodes.field_name(text=field_name)) field.append(body) return field
def make_field(self, types: Dict[str, List[Node]], domain: str, items: Tuple, env: BuildEnvironment = None, inliner: Inliner = None, location: Node = None) -> nodes.field: fieldname = nodes.field_name('', self.label) listnode = self.list_type() for fieldarg, content in items: par = nodes.paragraph() par.extend(self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong, env=env, inliner=inliner, location=location)) par += nodes.Text(' -- ') par += content listnode += nodes.list_item('', par) if len(items) == 1 and self.can_collapse: list_item = cast(nodes.list_item, listnode[0]) fieldbody = nodes.field_body('', list_item[0]) return nodes.field('', fieldname, fieldbody) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, item, env=None): fieldname = nodes.field_name('', self.label) backref = addnodes.pending_xref( '', refdomain="conda", reftype='requiredby', refexplicit=False, reftarget=env.ref_context['conda:package'], refdoc=env.docname ) backref += nodes.inline('', '') fieldbody = nodes.field_body('', backref) return nodes.field('', fieldname, fieldbody)
def patched_make_field(self, types, domain, items, **kw) -> nodes.field: """ """ # `kw` catches `env=None` needed for newer sphinx while maintaining # backwards compatibility when passed along further down! ## type: (List, unicode, Tuple) -> nodes.field def handle_item(fieldarg, content): """ """ par = nodes.paragraph() par += addnodes.literal_strong("", fieldarg) # Patch: this line added # par.extend(self.make_xrefs(self.rolename, domain, fieldarg, # addnodes.literal_strong)) if fieldarg in types: par += nodes.Text(" (") # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = "".join(n.astext() for n in fieldtype) typename = typename.replace("int", "python:int") typename = typename.replace("long", "python:long") typename = typename.replace("float", "python:float") typename = typename.replace("type", "python:type") par.extend( self.make_xrefs( self.typerolename, domain, typename, addnodes.literal_emphasis, **kw, ) ) else: par += fieldtype par += nodes.Text(")") par += nodes.Text(" -- ") par += content return par field_name = nodes.field_name("", self.label) if len(items) == 1 and self.can_collapse: field_arg, content = items[0] body_node = handle_item(field_arg, content) else: body_node = self.list_type() for field_arg, content in items: body_node += nodes.list_item("", handle_item(field_arg, content)) field_body = nodes.field_body("", body_node) return nodes.field("", field_name, field_body)
def make_field(self, directive): # treat content like docfields.Field value = directive.options.get(self.name) if value: name = nodes.field_name('', self.label) para = nodes.paragraph(rawsource=value) value = value.split(',') refs = [self.make_xref('', v.strip()) for v in value] content = [nodes.Text(',')] * (2 * len(refs) - 1) content[::2] = refs para += content body = nodes.field_body('', para) return nodes.field('', name, body)
def make_field(self, types, domain, items): fieldname = nodes.field_name('', self.label) listnode = self.list_type() if len(items) == 1 and self.can_collapse: return Field.make_field(self, types, domain, items[0]) for fieldarg, content in items: par = nodes.paragraph() par += self.make_xref(self.rolename, domain, fieldarg, nodes.strong) par += nodes.Text(' -- ') par += content listnode += nodes.list_item('', par) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, items): fieldname = nodes.field_name('', self.label) listnode = self.list_type() for fieldarg, content in items: par = nodes.paragraph() par += self.make_xref(self.rolename, domain, fieldarg, nodes.literal) if content and content[0].children: par += nodes.Text(' -- ') par += content listnode += nodes.list_item('', par) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, item): fieldarg, content = item fieldname = nodes.field_name("", self.label) if fieldarg: fieldname += nodes.Text(" ") fieldname += self.make_xref(self.rolename, domain, fieldarg, nodes.Text) if len(content) == 1 and ( isinstance(content[0], nodes.Text) or (isinstance(content[0], nodes.inline) and len(content[0]) == 1 and isinstance(content[0][0], nodes.Text)) ): content = [self.make_xref(self.bodyrolename, domain, content[0].astext(), contnode=content[0])] fieldbody = nodes.field_body("", nodes.paragraph("", "", *content)) return nodes.field("", fieldname, fieldbody)
def rfc2822_field(self, match): name = match.string[:match.string.find(':')] indented, indent, line_offset, blank_finish = \ self.state_machine.get_first_known_indented(match.end(), until_blank=1) fieldnode = nodes.field() fieldnode += nodes.field_name(name, name) fieldbody = nodes.field_body('\n'.join(indented)) fieldnode += fieldbody if indented: self.nested_parse(indented, input_offset=line_offset, node=fieldbody) return fieldnode, blank_finish
def process_motor_nodes(app, doctree): # Search doctree for Motor's methods and attributes whose docstrings were # copied from PyMongo, and fix them up for Motor: # 1. Add a 'callback' param (sometimes optional, sometimes required) to # all async methods. If the PyMongo method took no params, we create # a parameter-list from scratch, otherwise we edit PyMongo's list. # 2. Remove all version annotations like "New in version 2.0" since # PyMongo's version numbers are meaningless in Motor's docs. # # We do this here, rather than by registering a callback to Sphinx's # 'autodoc-process-signature' event, because it's way easier to handle the # parsed doctree before it's turned into HTML than it is to update the RST. for objnode in doctree.traverse(desc): if objnode['objtype'] in ('method', 'attribute'): signature_node = find_by_path(objnode, [desc_signature])[0] name = '.'.join([ signature_node['module'], signature_node['fullname']]) assert name.startswith('motor.') obj_motor_info = motor_info.get(name) if obj_motor_info: desc_content_node = find_by_path(objnode, [desc_content])[0] if obj_motor_info.get('is_async_method'): try: # Find the parameter list, a bullet_list instance parameters_node = find_by_path(desc_content_node, [field_list, field, field_body, bullet_list])[0] except IndexError: # PyMongo method has no parameters, create an empty # params list parameters_node = bullet_list() parameters_field_list_node = field_list('', field('', field_name('', 'Parameters '), field_body('', parameters_node))) desc_content_node.append(parameters_field_list_node) insert_callback( parameters_node, obj_motor_info['callback_required']) if obj_motor_info['is_pymongo_docstring']: # Remove all "versionadded", "versionchanged" and # "deprecated" directives from the docs we imported from # PyMongo version_nodes = find_by_path( desc_content_node, [versionmodified]) for version_node in version_nodes: version_node.parent.remove(version_node)
def create_attribute_list_node(self, app, docname, traceable): relationships = traceable.relationships # Determine which attributes to list in which order. attributes = traceable.attributes.copy() for relationship_name in relationships.keys(): attributes.pop(relationship_name, None) attributes.pop("title", None) # Create node to contain list of attributes. field_list_node = nodes.field_list() # Add relationship attributes. for relationship_name, relatives in sorted(relationships.items()): field_node = nodes.field() field_node += nodes.field_name(text=relationship_name) content = nodes.inline() for relative in sorted(relatives, key=lambda t: t.tag): if len(content): content += nodes.inline(text=", ") content += relative.make_reference_node(app.builder, docname) field_node += nodes.field_body("", content) field_list_node += field_node # Add non-relationship attributes. for attribute_name, attribute_value in sorted(attributes.items()): field_node = nodes.field() field_node += nodes.field_name(text=attribute_name) # Prepend space to avoid bug in the LaTeX builder of Sphinx v1.4 # which can cause \leavevmode to be stuck to following text. content = nodes.inline(text=" " + attribute_value) field_node += nodes.field_body("", content) field_list_node += field_node return field_list_node
def make_content(self, all_members): ret = nodes.section() doc = self.item if doc.doc: self.directive.state.nested_parse(to_list(doc.doc), 0, ret) check_parameters(self, doc) params, subtypes = extract_subtypes(self.item.name, self.item) rdoc = doc.return_val.doc rtype = doc.return_val.type if params or rtype or rdoc: with addto(ret, nodes.field_list()) as fields: if params: with addto(fields, nodes.field()) as field: field += nodes.field_name('Parameters', 'Parameters') with addto(field, nodes.field_body()) as body,\ addto(body, nodes.bullet_list()) as holder: holder.extend( make_parameters(params, mod=doc['sourcemodule'].name)) if rdoc: with addto(fields, nodes.field()) as field: field += nodes.field_name("Returns", "Returns") with addto(field, nodes.field_body()) as body,\ addto(body, nodes.paragraph()) as p: p += nodes.inline(rdoc, rdoc) if rtype: with addto(fields, nodes.field()) as field: field += nodes.field_name("Return Type", "Return Type") with addto(field, nodes.field_body()) as body, \ addto(body, nodes.paragraph()) as p: p += make_types(rtype, mod=doc['sourcemodule'].name) ret += self.document_subtypes(subtypes) return ret.children
def to_fields(x): to_definiton_list = False for v in x.values(): if isinstance(v, dict): to_definiton_list = True break if to_definiton_list: node = nodes.definition_list() previous_fieldlist = None for key, v in x.items(): df = nodes.definition_list_item() if isinstance(v, str): # embed field_list inside definition_list if previous_fieldlist is None: fv = previous_fieldlist = nodes.field_list() df.append(fv) node.append(df) else: fv = previous_fieldlist fvf = nodes.field() fv.append(fvf) fvf.append(nodes.field_name(text=key)) fvf.append(nodes.field_body(v, nodes.Text(v))) else: previous_fieldlist = None df.append(nodes.term(text=key)) dfv = nodes.definition() dfv.append(to_fields(v)) df.append(dfv) node.append(df) else: node = nodes.field_list() for key, v in x.items(): df = nodes.field() df.append(nodes.field_name(text=key)) dfv = nodes.field_body(v, nodes.Text(v)) df.append(dfv) node.append(df) return node
def dict_to_docinfo(data): """Render a key/val pair as a docutils field node.""" docinfo = nodes.docinfo() for key, value in data.items(): if not isinstance(value, (str, int, float)): value = json.dumps(value) value = str(value) field_node = nodes.field() field_node.source = value field_node += nodes.field_name(key, "", nodes.Text(key, key)) field_node += nodes.field_body(value, nodes.Text(value, value)) docinfo += field_node return docinfo
def make_field(self, types, # type: Dict[unicode, List[nodes.Node]] domain, # type: unicode items, # type: Tuple env=None, # type: BuildEnvironment ): # type: (...) -> nodes.field fieldname = nodes.field_name('', self.label) listnode = self.list_type() for fieldarg, content in items: par = nodes.paragraph() par.extend(self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong, env=env)) par += nodes.Text(' -- ') par += content listnode += nodes.list_item('', par) if len(items) == 1 and self.can_collapse: fieldbody = nodes.field_body('', listnode[0][0]) return nodes.field('', fieldname, fieldbody) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def patched_make_field(self, types, domain, items, env=None): """ This is a monkeypatch that prevents ivar cross references. :param self: :param types: :param domain: :param items: :param env: :return: .. seealso:: https://stackoverflow.com/questions/31784830/sphinx-ivar-tag-goes-looking-for-cross-references """ # type: (List, unicode, Tuple) -> nodes.field def handle_item(fieldarg, content): par = nodes.paragraph() par += addnodes.literal_strong('', fieldarg) # Patch: this line added if fieldarg in types: par += nodes.Text(' (') # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = u''.join(n.astext() for n in fieldtype) par.extend( self.make_xrefs(self.typerolename, domain, typename, addnodes.literal_emphasis)) else: par += fieldtype par += nodes.Text(')') par += nodes.Text(' -- ') par += content return par fieldname = nodes.field_name('', self.label) if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode = handle_item(fieldarg, content) else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item('', handle_item(fieldarg, content)) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def _build_markup(self): field_list = nodes.field_list() item = nodes.paragraph() item.append(field_list) if 'branch' in self.options: name = nodes.field_name(text="Branch") body = nodes.field_body() body.append(nodes.emphasis(text=self.branch_name)) field = nodes.field() field += [name, body] field_list.append(field) if 'commit' in self.options: name = nodes.field_name(text="Commit") body = nodes.field_body() if 'no_github_link' in self.options: body.append(self._commit_text_node()) else: body.append(self._github_link()) field = nodes.field() field += [name, body] field_list.append(field) if 'uncommitted' in self.options and self.repo.is_dirty(): item.append( nodes.warning( '', nodes.inline( text= "There were uncommitted changes when this was compiled." ))) if 'untracked' in self.options and self.repo.untracked_files: item.append( nodes.warning( '', nodes.inline( text= "There were untracked files when this was compiled."))) return [item]
def make_content(self, all_members): doc = self.item content = addnodes.desc_content() if doc.exports or doc.dependencies: with addto(content, nodes.field_list()) as fields: if doc.exports: with addto(fields, nodes.field()) as field: field += nodes.field_name('Exports', 'Exports') with addto(field, nodes.field_body()) as body: ref = doc[ 'exports'] # warning: not the same as doc.exports label = ref or '<anonymous>' link = addnodes.pending_xref( ref, nodes.paragraph(ref, label), refdomain='js', reftype='any', reftarget=ref, ) link['js:module'] = doc.name body += link if doc.dependencies: with addto(fields, nodes.field()) as field: self.make_dependencies(field, doc) if doc.doc: # FIXME: source offset self.directive.state.nested_parse( to_list(doc.doc, source=doc['sourcefile']), 0, content) self.directive.state.nested_parse(self.directive.content, 0, content) content += self.document_properties(all_members) return content
def make_field( self, types, # type: Dict[unicode, List[nodes.Node]] domain, # type: unicode items, # type: Tuple env=None, # type: BuildEnvironment ): # type: (...) -> nodes.field def handle_item(fieldarg, content): # type: (unicode, unicode) -> nodes.paragraph par = nodes.paragraph() par.extend( self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong, env=env)) if fieldarg in types: par += nodes.Text(' (') # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = u''.join(n.astext() for n in fieldtype) par.extend( self.make_xrefs(self.typerolename, domain, typename, addnodes.literal_emphasis, env=env)) else: par += fieldtype par += nodes.Text(')') par += nodes.Text(' -- ') par += content return par fieldname = nodes.field_name('', self.label) if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode = handle_item(fieldarg, content) else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item('', handle_item(fieldarg, content)) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types: Dict[str, List[Node]], domain: str, items: Tuple, env: "BuildEnvironment" = None) -> nodes.field: """Add emphasis once around the type hint. Modified from sphinx.util.docfields.TypedField. """ def handle_item(fieldarg: str, content: str) -> nodes.paragraph: par = nodes.paragraph() par.extend( self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong, env=env)) if fieldarg in types: par += nodes.Text(' (*') # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = fieldtype[0].astext() par.extend( self.make_xrefs(self.typerolename, domain, typename, nodes.generated, env=env)) else: par += fieldtype par += nodes.Text('*)') par += nodes.Text(' -- ') par += content return par fieldname = nodes.field_name('', self.label) if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode = handle_item(fieldarg, content) # type: nodes.Node else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item('', handle_item(fieldarg, content)) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, items, shapes=None, attrs=None, modname=None, typename=None): def handle_item(fieldarg, content): par = nodes.paragraph() if self.prefix: par += self.namefmt(self.prefix, self.prefix) par += self.make_xref(self.rolename, domain, fieldarg, self.namefmt, modname=modname, typename=typename) #par += self.namefmt(fieldarg, fieldarg) fieldtype = types.pop(fieldarg, None) fieldshape = shapes and shapes.pop(fieldarg, None) fieldattrs = attrs and attrs.pop(fieldarg, None) if fieldshape: shape = parse_shape(fieldshape[0].astext()) #par += nodes.Text(' %s'%shape) add_shape(par, shape, modname=modname) if fieldtype or fieldattrs: par += nodes.emphasis(' [',' [' ) if fieldtype: if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): thistypename = fieldtype[0].astext() #typename = u''.join(n.astext() for n in fieldtype) par += self.make_xref(self.typerolename, domain, thistypename, modname=modname, typename=typename) else: par += fieldtype if fieldattrs: if fieldtype: par += nodes.emphasis(',',',') par += fieldattrs if fieldtype or fieldattrs: par += nodes.emphasis(']',']') if content: par += nodes.Text(' :: ') par += content return par if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode = handle_item(fieldarg, content) else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item('', handle_item(fieldarg, content)) label = self.label or '' fieldname = nodes.field_name('', label) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types: Dict[str, List[Node]], domain: str, items: Tuple, env: BuildEnvironment = None, inliner: Inliner = None, location: Node = None) -> nodes.field: def handle_item(fieldarg: str, content: str) -> nodes.paragraph: par = nodes.paragraph() par.extend( self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong, env=env)) if fieldarg in types: par += nodes.Text(' (') # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = fieldtype[0].astext() par.extend( self.make_xrefs(self.typerolename, domain, typename, addnodes.literal_emphasis, env=env, inliner=inliner, location=location)) else: par += fieldtype par += nodes.Text(')') par += nodes.Text(' -- ') par += content return par fieldname = nodes.field_name('', self.label) if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode: Node = handle_item(fieldarg, content) else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item('', handle_item(fieldarg, content)) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def transform_content(self, contentnode: addnodes.desc_content) -> None: fieldlist = nodes.field_list() access = None if "readonly" in self.options: access = _("read-only") if "writeonly" in self.options: access = _("write-only") if "readwrite" in self.options: access = _("read & write") if access: content = nodes.Text(access) fieldname = nodes.field_name("", _("Access")) fieldbody = nodes.field_body("", nodes.paragraph("", "", content)) field = nodes.field("", fieldname, fieldbody) fieldlist += field emits = self.options.get("emits-changed", None) if emits: content = nodes.Text(emits) fieldname = nodes.field_name("", _("Emits Changed")) fieldbody = nodes.field_body("", nodes.paragraph("", "", content)) field = nodes.field("", fieldname, fieldbody) fieldlist += field if len(fieldlist) > 0: contentnode.insert(0, fieldlist)
def make_field(self, types, domain, item): fieldarg, content = item fieldname = nodes.field_name('', self.label) if fieldarg: fieldname += nodes.Text(' ') fieldname += self.make_xref(self.rolename, domain, fieldarg, nodes.Text) if len(content) == 1 and ( isinstance(content[0], nodes.Text) or (isinstance(content[0], nodes.inline) and len(content[0]) == 1 and isinstance(content[0][0], nodes.Text))): content = [self.make_xref(self.bodyrolename, domain, content[0].astext(), contnode=content[0])] fieldbody = nodes.field_body('', nodes.paragraph('', '', *content)) return nodes.field('', fieldname, fieldbody)
def _group_fields(fields): content = collections.defaultdict(nodes.field_list) for name, body in fields: field_parts = name.astext().split() if len(field_parts) > 1: content[field_parts[0]].append( nodes.field("", nodes.field_name(text=field_parts[1]), body) ) else: content[field_parts[0]] = body result = nodes.field_list() for section_id, section_label in SECTION_MAPPING.items(): items = content[section_id] if len(items) > 0: if isinstance(items, nodes.field_body): body = items else: body = nodes.field_body("", items) result.append( nodes.field("", nodes.field_name(text=section_label), body) ) return result
def make_super(self): doc = self.item if not doc.superclass: return [] sup_link = addnodes.pending_xref( doc.superclass.name, nodes.paragraph(doc.superclass.name, doc.superclass.name), refdomain='js', reftype='class', reftarget=doc.superclass.name, ) sup_link['js:module'] = doc.superclass['sourcemodule'].name return nodes.field( '', nodes.field_name("Extends", "Extends"), nodes.field_body(doc.superclass.name, sup_link), )
def patched_make_field( self, # type: TypedField types, # type: typing.Dict[str, typing.List[nodes.Node]] domain, # type: str items, # type: typing.Tuple env=None, # type: typing.Any ): # type: (...) -> nodes.field def handle_item(fieldarg, content): # type: (str, str) -> nodes.paragraph par = nodes.paragraph() par += addnodes.literal_strong("", fieldarg) # Patch: this line added # par.extend(self.make_xrefs(self.rolename, domain, fieldarg, # addnodes.literal_strong, env=env)) if fieldarg in types: par += nodes.Text(" (") # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = u"".join(n.astext() for n in fieldtype) par.extend( self.make_xrefs( self.typerolename, domain, typename, addnodes.literal_emphasis, env=env, ) ) else: par += fieldtype par += nodes.Text(")") par += nodes.Text(" -- ") par += content return par fieldname = nodes.field_name("", self.label) if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode = handle_item(fieldarg, content) else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item("", handle_item(fieldarg, content)) fieldbody = nodes.field_body("", bodynode) return nodes.field("", fieldname, fieldbody)
def make_mixins(self): doc = self.item if not doc.mixins: return [] ret = nodes.field('', nodes.field_name("Mixes", "Mixes")) with addto(ret, nodes.field_body()) as body: with addto(body, nodes.bullet_list()) as mixins: for mixin in sorted(doc.mixins, key=lambda m: m.name): mixin_link = addnodes.pending_xref( mixin.name, nodes.paragraph(mixin.name, mixin.name), refdomain='js', reftype='mixin', reftarget=mixin.name ) mixin_link['js:module'] = mixin['sourcemodule'].name mixins += nodes.list_item('', mixin_link) return ret
def make_field(self, types: Dict[str, List[Node]], domain: str, items: Tuple, env: BuildEnvironment = None, inliner: Inliner = None, location: Node = None) -> nodes.field: """Copy+Paste of TypedField.make_field() from Sphinx version 4.3.2. The first and second nodes.Text() instance are changed in this implementation to be ' : ' and '' respectively (instead of ' (' and ')'). TODO: Ask sphinx devs if there is a better way to support this that is less copy+pasty. (thomasvandoren, 2015-03-17) """ def handle_item(fieldarg: str, content: str) -> nodes.paragraph: par = nodes.paragraph() par.extend(self.make_xrefs(self.rolename, domain, fieldarg, addnodes.literal_strong, env=env)) if fieldarg in types: par += nodes.Text(' : ') # NOTE: using .pop() here to prevent a single type node to be # inserted twice into the doctree, which leads to # inconsistencies later when references are resolved fieldtype = types.pop(fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = fieldtype[0].astext() par.extend(self.make_xrefs(self.typerolename, domain, typename, addnodes.literal_emphasis, env=env, inliner=inliner, location=location)) else: par += fieldtype par += nodes.Text('') par += nodes.Text(' -- ') par += content return par fieldname = nodes.field_name('', self.label) if len(items) == 1 and self.can_collapse: fieldarg, content = items[0] bodynode: Node = handle_item(fieldarg, content) else: bodynode = self.list_type() for fieldarg, content in items: bodynode += nodes.list_item('', handle_item(fieldarg, content)) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)