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 _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 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 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 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 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): 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 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_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, 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, 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 _parse_field(self, tree, children): numargs = 0 while tree.childNodes[numargs+1].tagName == 'arg': numargs += 1 tag = children[0] args = children[1:1+numargs] body = children[1+numargs:] name = nodes.field_name('','', *children[:1+numargs]) body = nodes.field_body('', *children[1+numargs:]) return (name, body)
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, 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 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, **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, 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, 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, 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_dependencies(self, field, doc): field += nodes.field_name("Depends On", "Depends On") with addto(field, nodes.field_body()) as body: with addto(body, nodes.bullet_list()) as deps: for dep in sorted(doc.dependencies): ref = addnodes.pending_xref( dep, nodes.paragraph(dep, dep), refdomain='js', reftype='module', reftarget=dep, ) deps += nodes.list_item(dep, ref)
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, 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 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 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 transform(cls, node): split = node[0].rawsource.split(None, 2) type = None if len(split) == 3: name, type, value = split elif len(split) == 2: name, value = split else: raise Exception('Too Few arguments.') node.attributes['names'].append(name) if type: node.insert(1, field_type(type)) node[0].replace_self(nodes.field_name(value, value))
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 make_field(self, types, # type: Dict[unicode, List[nodes.Node]] domain, # type: unicode item, # type: Tuple env=None, # type: BuildEnvironment ): # type: (...) -> nodes.field fieldarg, content = item fieldname = nodes.field_name('', self.label) if fieldarg: fieldname += nodes.Text(' ') fieldname.extend(self.make_xrefs(self.rolename, domain, fieldarg, nodes.Text, env=env)) 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_xrefs(self.bodyrolename, domain, content[0].astext(), contnode=content[0], env=env) fieldbody = nodes.field_body('', nodes.paragraph('', '', *content)) return nodes.field('', fieldname, fieldbody)
def make_field( self, types: Dict[str, List[nodes.Node]], domain: str, items: Tuple[str, List[nodes.inline]], env: BuildEnvironment = None ) -> nodes.field: def makerefs(rolename, name, node): return self.make_xrefs(rolename, domain, name, node, env=env) def handle_item(fieldarg: str, content: List[nodes.inline]) -> nodes.definition_list_item: head = nodes.term() head += makerefs(self.rolename, fieldarg, addnodes.literal_strong) fieldtype = types.pop(fieldarg, None) if fieldtype is not None: head += nodes.Text(' : ') if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): text_node, = fieldtype # type: nodes.Text head += makerefs(self.typerolename, text_node.astext(), addnodes.literal_emphasis) #typename = ''.join(n.astext() for n in fieldtype) #head += makerefs(self.typerolename, typename, addnodes.literal_emphasis) else: head += fieldtype body_content = nodes.paragraph('', '', *content) body = nodes.definition('', body_content) return nodes.definition_list_item('', head, body) 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 += handle_item(fieldarg, content) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, # type: Dict[str, List[nodes.Node]] domain, # type: str items, # type: Tuple env=None, # type: BuildEnvironment ): # type: (...) -> nodes.field def handle_item(fieldarg, content): # type: (str, 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)) 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, env=None): """Copy+Paste of TypedField.make_field() from Sphinx version 1.2.3. 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, content): par = nodes.paragraph() par += self.make_xref(self.rolename, domain, fieldarg, nodes.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 += self.make_xref(self.typerolename, domain, typename) 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 patched_make_field(self, types, domain, items): # 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 = u''.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)) 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): config = self.state.document.settings.env.config model_name = self.arguments[0] optfields = self.options.get('fields') if not optfields: fields = _client.model(model_name).keys() else: fields = optfields.split(' ') l = [ x for x in fields if x not in ['create_uid', 'create_date', 'write_uid', 'write_date'] ] res = _client.execute(model_name, 'fields_get', l, context={'lang': config.odoo_lang}) classes = [config.odoodoc_fieldlistclass] if 'class' in self.options: classes.extend(self.options['class']) 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 res.iteritems() # only display if there's a help text if v.get('help')), classes=classes) ]
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 run(self, reader: LineReader, document: Element) -> bool: if reader.lineno != 0: return False reader.readline() field_list = nodes.field_list() field_list.source, field_list.line = reader.get_source_and_line() for line in reader: if self.pattern.match(line): break elif ':' in line: key, value = line.split(':') field_name = nodes.field_name('', key.strip()) field_body = nodes.field_body('', nodes.paragraph('', value.strip())) field_list += nodes.field('', field_name, field_body) else: # Not a frontmatter, rollback lines = len(field_list) + 2 reader.step(-lines) return False document += field_list return True
def make_field(self, types, domain, item, env=None): fieldarg, content = item fieldname = nodes.field_name('', self.label) if fieldarg: fieldname += nodes.Text(' ') fieldname.extend( self.make_xrefs(self.rolename, domain, fieldarg, nodes.Text, env=env)) 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_xrefs(self.bodyrolename, domain, content[0].astext(), contnode=content[0], env=env) fieldbody = nodes.field_body('', nodes.paragraph('', '', *content)) 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)) if content and content[0].astext(): par += nodes.Text(' ') par += content listnode += nodes.list_item('', par) source = env.ref_context['conda:package'] backrefs = env.domains['conda'].data['backrefs'].setdefault( fieldarg, set()) backrefs.add((env.docname, source)) fieldbody = nodes.field_body('', listnode) return nodes.field('', fieldname, fieldbody)
def patched_make_field(self, types, domain, items, env): # type: (list, str, 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) 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 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, domain, item, env=None): fieldarg, fieldtype = item body = d_nodes.paragraph() if fieldarg: body.extend(self.make_xrefs(self.rolename, domain, fieldarg, s_nodes.literal_strong, env=env)) body += d_nodes.Text('--') typename = u''.join(n.astext() for n in fieldtype) body.extend( self.make_xrefs(self.typerolename, domain, typename, s_nodes.literal_emphasis, env=env)) fieldname = d_nodes.field_name('', self.label) fieldbody = d_nodes.field_body('', body) node = d_nodes.field('', fieldname, fieldbody) node['eql-name'] = self.name node['eql-opname'] = fieldarg if typename: node['eql-optype'] = typename return node
def make_field(self, types, domain, item, env=None): fieldname = d_nodes.field_name('', self.label) fieldarg, content = item body = d_nodes.paragraph() body.extend(self.make_xrefs(self.rolename, domain, fieldarg, s_nodes.literal_strong, env=env)) typename = None if fieldarg in types: body += d_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], d_nodes.Text): typename = u''.join(n.astext() for n in fieldtype) body.extend( self.make_xrefs(self.typerolename, domain, typename, s_nodes.literal_emphasis, env=env)) else: body += fieldtype body += d_nodes.Text(')') body += d_nodes.Text(' -- ') body += content fieldbody = d_nodes.field_body('', body) node = d_nodes.field('', fieldname, fieldbody) node['eql-name'] = self.name node['eql-paramname'] = fieldarg if typename: node['eql-paramtype'] = typename return node
def dict_to_fm_field_list(self, data: Dict[str, Any], language_code: str, line: int = 0) -> nodes.field_list: """Render each key/val pair as a docutils ``field_node``. Bibliographic keys below will be parsed as Markdown, all others will be left as literal text. The field list should be at the start of the document, and will then be converted to a `docinfo` node during the `docutils.docutils.transforms.frontmatter.DocInfo` transform (priority 340), and bibliographic keys (or their translation) will be converted to nodes:: {'author': docutils.nodes.author, 'authors': docutils.nodes.authors, 'organization': docutils.nodes.organization, 'address': docutils.nodes.address, 'contact': docutils.nodes.contact, 'version': docutils.nodes.version, 'revision': docutils.nodes.revision, 'status': docutils.nodes.status, 'date': docutils.nodes.date, 'copyright': docutils.nodes.copyright, 'dedication': docutils.nodes.topic, 'abstract': docutils.nodes.topic} Also, the 'dedication' and 'abstract' will be placed outside the `docinfo`, and so will always be shown in the document. If using sphinx, this `docinfo` node will later be extracted from the AST, by the `DoctreeReadEvent` transform (priority 880), calling `MetadataCollector.process_doc`. In this case keys and values will be converted to strings and stored in `app.env.metadata[app.env.docname]` See https://www.sphinx-doc.org/en/master/usage/restructuredtext/field-lists.html for docinfo fields used by sphinx. """ field_list = nodes.field_list() bibliofields = get_language(language_code).bibliographic_fields state_machine = MockStateMachine(self, line) state = MockState(self, state_machine, line) for key, value in data.items(): if not isinstance(value, (str, int, float, date, datetime)): value = json.dumps(value) value = str(value) if key in bibliofields: para_nodes, _ = state.inline_text(value, line) body_children = [nodes.paragraph("", "", *para_nodes)] else: body_children = [nodes.Text(value, 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, *body_children) field_list += field_node return field_list
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, env=None, **kwargs): def handle_item(fieldarg, content): """Handles translating an item into a node. :param str fieldarg: The name of the field. This is either in the format of 'some_field', 'some_field|object', or 'some_field|objectproperty'. If there is a `|` character in the fieldarg it is treated differently in order to generate a sub-list for objects. :param list(docutils.nodes.node) content: The content field which contains a list of node types to render. :returns: A tuple containing the item as a node paragraph and a list node if the item is an object, otherwise None. """ # store a copy of the original value for looking up types within # this function. orig_fieldarg = fieldarg # Determine if the field is an object or not. is_object = False fieldargs = fieldarg.split('|') fieldarg = fieldargs[0] if len(fieldargs) == 2 and fieldargs[1] == 'object': is_object = True par = nodes.paragraph() par += self.make_xref(self.rolename, domain, fieldarg, addnodes.literal_strong) if orig_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(orig_fieldarg) if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): typename = u''.join(n.astext() for n in fieldtype) par += self.make_xref(self.typerolename, domain, typename, addnodes.literal_emphasis) else: par += fieldtype par += nodes.Text(')') par += nodes.Text(' -- ') # We need to add each child node individually. If we don't and # just do `par += content` the order of the rendered nodes sometimes # is generated in an unexpected order. for item in content: for node in item.children: par += node # If the item is an object we need to create a sub-list to show # all of the object's properties. ul = None if is_object: ul = self.list_type() obj_pos = items.index((orig_fieldarg, content)) # Loop over all items after the current item and add them to # the sub list until we reach the end of the item's properties. for obj_prop, content in items[obj_pos + 1:]: fieldargs = obj_prop.split('|') if len(fieldargs ) == 2 and fieldargs[1] == 'objectproperty': # Remove the object property from items so we don't # document it again as we iterate over items outside # of this function. items.remove((obj_prop, content)) li, _ = handle_item(obj_prop, content) ul += nodes.list_item('', li) else: break return (par, ul) 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: li, ul = handle_item(fieldarg, content) # If the item was an object we will have a sub-list returned # that we should add to the list item. if ul: li += ul bodynode += nodes.list_item('', li) fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)
def make_field(self, types, domain, item, env=None): fieldarg, content = item fieldname = nodes.field_name('', '', nodes.emphasis('', self.label)) fieldbody = nodes.field_body('') return nodes.field('', fieldname, fieldbody)
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 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) if self.cabal_meta.removed is not None: field = nodes.field('') field_name = nodes.field_name('Removed', 'Removed') if isinstance(self.cabal_meta.removed, StrictVersion): since = 'Cabal ' + str(self.cabal_meta.removed) 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 _run_role(self, role): html = self._get_readme_html(os.path.join(role, 'README.md')) section = self._section_block(title='Role Documentation', raw_html=True, text=html) defaults_file = os.path.join(role, 'defaults', 'main.yml') if os.path.exists(defaults_file): with open(defaults_file) as f: role_defaults = DOCYAML.load(f.read()) section.append( self._yaml_section( to_yaml_data=role_defaults, section_title='Role Defaults', section_text='This section highlights all of the defaults' ' and variables set within the "{}"' ' role.'.format(os.path.basename(role)))) vars_path = os.path.join(role, 'vars') if os.path.exists(vars_path): for v_file in os.listdir(vars_path): vars_file = os.path.join(vars_path, v_file) with open(vars_file) as f: vars_values = DOCYAML.load(f.read()) if vars_values: section.append( self._yaml_section( to_yaml_data=vars_values, section_title='Role Variables: {}'.format(v_file))) test_list = nodes.field_list() test_section = self._section_block( title='Molecule Scenarios', text='Molecule is being used to test the "{}" role. The' ' following section highlights the drivers in service' ' and provides an example playbook showing how the role' ' is leveraged.'.format(os.path.basename(role))) molecule_path = os.path.join(role, 'molecule') if os.path.exists(molecule_path): for test in os.listdir(molecule_path): molecule_section = self._section_block( title='Scenario: {}'.format(test)) molecule_file = os.path.join(molecule_path, test, 'molecule.yml') if not os.path.exists(molecule_file): continue with open(molecule_file) as f: molecule_conf = DOCYAML.load(f.read()) driver_data = molecule_conf.get('driver') if driver_data: molecule_section.append( nodes.field_name( text='Driver: {}'.format(driver_data['name']))) options = driver_data.get('options') if options: molecule_section.append( self._yaml_section( to_yaml_data=options, section_title='Molecule Options')) provisioner_data = molecule_conf.get('provisioner') if provisioner_data: inventory = provisioner_data.get('inventory') if inventory: molecule_section.append( self._yaml_section( to_yaml_data=inventory, section_title='Molecule Inventory')) molecule_playbook_path = os.path.join(molecule_path, test, 'converge.yml') if not os.path.exists(molecule_playbook_path): molecule_playbook_path = os.path.join( molecule_path, test, 'playbook.yml') with open(molecule_playbook_path) as f: molecule_playbook = DOCYAML.load(f.read()) molecule_section.append( self._yaml_section( to_yaml_data=molecule_playbook, section_title='Example {} playbook'.format(test))) test_list.append(molecule_section) else: test_section.append(test_list) section.append(test_section) self.run_returns.append(section) # Document any libraries nested within the role library_path = os.path.join(role, 'library') if os.path.exists(library_path): self.options['documentation'] = True self.options['examples'] = True for lib in os.listdir(library_path): if lib.endswith('.py'): self._run_module( module=self.load_module( filename=os.path.join(library_path, lib)), module_title='Embedded module: {}'.format(lib), example_title='Examples for embedded module')
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: if fieldarg: 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, name, content): fieldname = nodes.field_name('', name) fieldbody = nodes.field_body('', nodes.paragraph('', '', content)) return nodes.field('', fieldname, fieldbody)
def run(self): """ Main directive entry function, called by docutils upon encountering the directive. This directive is meant to be quite easily subclassable, so it delegates to several additional methods. What it does: * find out if called as a domain-specific directive, set self.domain * create a `desc` node to fit all description inside * parse standard options, currently `noindex` * create an index node if needed as self.indexnode * parse all given signatures (as returned by self.get_signatures()) using self.handle_signature(), which should either return a name or raise ValueError * add index entries using self.add_target_and_index() * parse the content and handle doc fields in it This method was copied and adapted from sphinx.directive.ObjectDescription.run() (in Sphinx 1.1) """ if ':' in self.name: self.domain, self.objtype = self.name.split(':', 1) else: self.domain, self.objtype = '', self.name self.env = self.state.document.settings.env self.indexnode = addnodes.index(entries=[]) node = addnodes.desc() node.document = self.state.document node['domain'] = self.domain # 'desctype' is a backwards compatible attribute node['objtype'] = node['desctype'] = self.objtype node['noindex'] = noindex = ('noindex' in self.options) self.names = [] signatures = self.get_signatures() name = None for i, sig in enumerate(signatures): # add a signature node for each signature in the current unit # and add a reference target for it signode = addnodes.desc_signature(sig, '') signode['first'] = False node.append(signode) try: # name can also be a tuple, e.g. (classname, objname); # this is strictly domain-specific (i.e. no assumptions may # be made in this base class) name = self.handle_signature(sig, signode) except ValueError: # signature parsing failed signode.clear() signode += addnodes.desc_name(sig, sig) continue # we don't want an index entry here if not noindex and name is not None and name not in self.names: # only add target and index entry if this is the first # description of the object with this name in this desc block self.names.append(name) self.add_target_and_index(name, sig, signode) contentnode = addnodes.desc_content() node.append(contentnode) if self.names: # needed for association of version{added,changed} directives self.env.temp_data['object'] = self.names[0] self.before_content() self.state.nested_parse(self.content, self.content_offset, contentnode) for child in contentnode: if isinstance(child, nodes.field_list): child.insert( 0, nodes.field( '', nodes.field_name('', u'param std::string eventName'), nodes.field_body( '', nodes.paragraph('', u'"{0}"'.format(name))))) child.append( nodes.field( '', nodes.field_name( '', u'param std::string subscriberIdentifier'), nodes.field_body('', nodes.paragraph('', u'')))) DocFieldTransformer(self).transform_all(contentnode) self.env.temp_data['object'] = None self.after_content() return [self.indexnode, node]
def handle_doc_fields(self, node): """ Convert field lists with known keys inside the description content into better-looking equivalents. """ # 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 = [] pfield = 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) typdesc = _(self.doc_fields_with_arg[typ]) if _is_only_paragraph(fbody): children = fbody.children[0].children else: children = fbody.children if typdesc == '%param': if not params: # add the field that later gets all the parameters pfield = nodes.field() 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.append(dlitem) elif typdesc == '%type': typenodes = fbody.children if _is_only_paragraph(fbody): typenodes = ([nodes.Text(' (')] + typenodes[0].children + [nodes.Text(')')]) param_types[obj] = typenodes else: fieldname = typdesc + ' ' nfield = nodes.field() nfieldname = nodes.field_name(fieldname, fieldname) nfield += nfieldname node = nfieldname if typ in self.doc_fields_with_linked_arg: node = addnodes.pending_xref( obj, reftype='obj', refcaption=False, reftarget=obj, modname=self.env.currmodule, classname=self.env.currclass) nfieldname += node node += nodes.Text(obj, obj) nfield += nodes.field_body() nfield[1] += fbody.children new_list += nfield except (KeyError, ValueError): fnametext = fname.astext() try: typ = _(self.doc_fields_without_arg[fnametext]) except KeyError: # at least capitalize the field name typ = fnametext.capitalize() fname[0] = nodes.Text(typ) new_list += field if params: if len(params) == 1: pfield += nodes.field_name('', _('Parameter')) pfield += nodes.field_body() pfield[1] += params[0][0] else: pfield += nodes.field_name('', _('Parameters')) pfield += nodes.field_body() pfield[1] += nodes.bullet_list() pfield[1][0].extend(params) for param, type in param_types.iteritems(): if param in param_nodes: param_nodes[param][1:1] = type child.replace_self(new_list)
def run(self): env = self.state.document.settings.env txb_name = self.arguments[0] txb_id = nodes.make_id(txb_name) # First, make a generic desc() node to be the parent. node = sphinx.addnodes.desc() node.document = self.state.document node['objtype'] = 'directive' # Next, make a signature node. This creates a permalink and a highlighted background when the link is selected. title = sphinx.addnodes.desc_signature(txb_name, '') title['ids'].append(txb_name) title['ids'].append(txb_id) title['names'].append(txb_name) title['first'] = False title['objtype'] = 'directive' self.add_name(title) title.set_class('directive-title') # Finally, add a desc_name() node to display the name of the # configuration variable. title += sphinx.addnodes.desc_name(txb_name, txb_name) node.append(title) if ('class' in self.options): title.set_class(self.options.get('class')) # This has to be a distinct node before the title. if nested then the browser will scroll forward to just past the title. anchor = nodes.target('', '', names=[txb_name]) # Second (optional) arg is 'msgNode' - no idea what I should pass for that # or if it even matters, although I now think it should not be used. self.state.document.note_explicit_target(title) env.domaindata['txb']['directive'][txb_name] = env.docname fl = nodes.field_list() if ('keys' in self.options): key_field = nodes.field() key_field.append(nodes.field_name(text='Secondary Keys')) key_value = nodes.field_list() key_body = nodes.field_body() key_body.append(key_value) key_field.append(key_body) key_list = self.options['keys'].split('|') for key in key_list: tag = key descr = '' if ':' in key: (tag, descr) = key.split(':') tag = tag.strip() descr = descr.strip() key_value.append(self.make_field(tag, descr)) fl.append(key_field) if ('arg' in self.options): fl.append(self.make_field('Argument', self.options['arg'])) if ('value' in self.options): fl.append(self.make_field('Value', self.options['value'])) # Get any contained content nn = nodes.compound() self.state.nested_parse(self.content, self.content_offset, nn) # Create an index node so that Sphinx adds this directive to the index. indexnode = sphinx.addnodes.index(entries=[]) indexnode['entries'].append( ('single', _('%s') % txb_name, txb_id, '', '')) return [indexnode, node, fl, nn]
def _run_role(self, role): section = self._section_block( title='Role Documentation', text='Welcome to the "{}" role documentation.'.format( os.path.basename(role))) defaults_file = os.path.join(role, 'defaults', 'main.yml') if os.path.exists(defaults_file): with open(defaults_file) as f: role_defaults = yaml.safe_load(f.read()) section.append( self._yaml_section( to_yaml_data=role_defaults, section_title='Role Defaults', section_text='This section highlights all of the defaults' ' and variables set within the "{}"' ' role.'.format(os.path.basename(role)))) vars_path = os.path.join(role, 'vars') if os.path.exists(vars_path): for v_file in os.listdir(vars_path): vars_file = os.path.join(vars_path, v_file) with open(vars_file) as f: vars_values = yaml.safe_load(f.read()) section.append( self._yaml_section( to_yaml_data=vars_values, section_title='Role Variables: {}'.format(v_file))) test_list = nodes.field_list() test_section = self._section_block( title='Molecule Scenarios', text='Molecule is being used to test the "{}" role. The' ' following section highlights the drivers in service' ' and provides an example playbook showing how the role' ' is leveraged.'.format(os.path.basename(role))) molecule_path = os.path.join(role, 'molecule') if os.path.exists(molecule_path): for test in os.listdir(molecule_path): molecule_section = self._section_block( title='Scenario: {}'.format(test)) molecule_file = os.path.join(molecule_path, test, 'molecule.yml') with open(molecule_file) as f: molecule_conf = yaml.safe_load(f.read()) driver_data = molecule_conf.get('driver') if driver_data: molecule_section.append( nodes.field_name( text='Driver: {}'.format(driver_data['name']))) options = driver_data.get('options') if options: molecule_section.append( self._yaml_section( to_yaml_data=options, section_title='Molecule Options')) provisioner_data = molecule_conf.get('provisioner') if provisioner_data: inventory = provisioner_data.get('inventory') if inventory: molecule_section.append( self._yaml_section( to_yaml_data=inventory, section_title='Molecule Inventory')) molecule_playbook_path = os.path.join(molecule_path, test, 'playbook.yml') with open(molecule_playbook_path) as f: molecule_playbook = yaml.safe_load(f.read()) molecule_section.append( self._yaml_section( to_yaml_data=molecule_playbook, section_title='Example {} playbook'.format(test))) test_list.append(molecule_section) else: test_section.append(test_list) section.append(test_section) self.run_returns.append(section)
def run(self): # Tests don't have to have contents now, so check for it but don't assert: self.document = self.state_machine.document text = [] if self.content: text = '\n'.join(self.content) # Create the admonition node, to be populated by `nested_parse`. self.name = self.arguments[0] if 'test_time' in self.options: self.test_time = self.options['test_time'] # test_procedure name #if 'test_procedure' in self.options: if 'test_procedure' in self.options: self.test_procedure = self.options['test_procedure'] else: self.assert_has_content() proc = TestProcedure(self.name + "_procedure") self.test_procedure = proc.name if 'setup' in self.options: proc.setup = self.options['setup'] else: proc.setup = "" proc.content = self.content self.parsed('test_procedure').append(proc) term = nodes.term() term += nodes.strong(text=self.arguments[0]) targetnode = self.make_targetnode() deflist = nodes.definition_list() test_def = nodes.definition_list_item() test_def += term defn = nodes.definition() test_def += defn deflist += test_def if 'parameters' in self.options: params = self.parse_parameters() defn += nodes.paragraph(text="Parameters:") for param in params: name = param['param'] field_list = nodes.field_list() param_field = nodes.field() param_field_name = nodes.field_name() param_field_name += nodes.Text(name) param_field += param_field_name param_field_body = nodes.field_body() choices_str = param['choices_str'] if (len(choices_str) < 50): param_field_body += nodes.paragraph(text=choices_str) else: choices = param['choices'] param_field_body += nodes.raw('', ' \\ \n\n', format="latex") for choice in choices: param_field_body += nodes.paragraph(text=choice) param_field += param_field_body field_list += param_field name = self.arguments[0].strip() + "param" + name param_target = nodes.target('', '', ids=[nodes.make_id(name)]) name = nodes.fully_normalize_name(name) param_target['names'].append(name) self.state_machine.document.note_explicit_target( param_target, param_target) defn += param_target defn += field_list # Parse the directive contents. self.state.nested_parse(self.content, self.content_offset, defn) option_map = {} option_map['configurations'] = 'Valid configurations' option_map['setup'] = 'Required setup' option_map['test_time'] = 'Test time (min)' option_map['priority'] = 'Priority' option_map['test_procedure'] = 'Test procedure' field_list = self.options_to_field_list(option_map) if (field_list != None): defn += field_list self.parsed('test').append(self) return [targetnode, deflist]
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 Motor Tornado 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 (desc_content_node.line is None and obj_motor_info['is_pymongo_docstring']): maybe_warn_about_code_block(name, desc_content_node) if obj_motor_info['is_async_method']: # Might be a handwritten RST with "coroutine" already. if not has_coro_annotation(signature_node): coro_annotation = addnodes.desc_annotation( 'coroutine ', 'coroutine ', classes=['coro-annotation']) signature_node.insert(0, coro_annotation) if not is_asyncio_api(name): retval = ("If a callback is passed, returns None, else" " returns a Future.") callback_p = paragraph('', Text(retval)) # Find the parameter list. parameters_nodes = find_by_path( desc_content_node, [ field_list, field, field_body, (bullet_list, paragraph)]) if parameters_nodes: parameters_node = parameters_nodes[0] else: # 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) if retval not in str(desc_content_node): desc_content_node.append(callback_p) 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: Dict[str, List[nodes.Node]], domain: str, items: Tuple, env: Optional[BuildEnvironment] = None, **kwargs, # To support Sphinx 4.1 and later ) -> nodes.field: def handle_item(fieldarg: str, content: List[nodes.Element]) -> nodes.paragraph: par = nodes.paragraph() par.extend( self.make_xrefs( self.rolename, domain, fieldarg, addnodes.literal_strong, env=env, **kwargs, # To support Sphinx 4.1 and later ) ) 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) ) else: par += fieldtype par += nodes.Text(')') if (content and len(content) == 1 and isinstance(content[0], nodes.inline) and not content[0].children): return par par += nodes.Text(" -- ") par += content return par fieldname = nodes.field_name('', self.label) bodynode: nodes.Node 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)) # type: ignore fieldbody = nodes.field_body('', bodynode) return nodes.field('', fieldname, fieldbody)