def description_table(descriptions, widths, headers): # generate table-root tgroup = nodes.tgroup(cols=len(widths)) for width in widths: tgroup += nodes.colspec(colwidth=width) table = nodes.table() table += tgroup # generate table-header thead = nodes.thead() row = nodes.row() for header in headers: entry = nodes.entry() entry += nodes.paragraph(text=header) row += entry thead += row tgroup += thead # generate table-body tbody = nodes.tbody() for desc in descriptions: row = nodes.row() for col in desc: entry = nodes.entry() if not isinstance(col, basestring): col = str(col) paragraph = nodes.paragraph() paragraph += nodes.Text(col) entry += paragraph row += entry tbody += row tgroup += tbody return table
def create_cross_table(self, app, docname, node, matrix, options): table = nodes.table() table["classes"].append("traceables-crosstable") tgroup = nodes.tgroup(cols=len(matrix.secondaries), colwidths="auto") table += tgroup # Add column specifications. tgroup += nodes.colspec(colwidth=1) for column in matrix.secondaries: tgroup += nodes.colspec(colwidth=1) # Add heading row. thead = nodes.thead() tgroup += thead row = nodes.row() thead += row entry = nodes.entry() row += entry for secondary in matrix.secondaries: entry = nodes.entry() row += entry container = nodes.container() entry += container inline = nodes.inline() container += inline paragraph = nodes.paragraph() inline += paragraph paragraph += secondary.make_reference_node(app.builder, docname) # Add table body. tbody = nodes.tbody() tgroup += tbody for primary in matrix.primaries: row = nodes.row() tbody += row entry = nodes.entry() row += entry paragraph = nodes.paragraph() entry += paragraph paragraph += primary.make_reference_node(app.builder, docname) for is_related in matrix.get_boolean_row(primary): entry = nodes.entry() row += entry if is_related: checkmark = traceable_checkmark() entry += checkmark checkmark += nodes.inline(u"\u2714", u"\u2714") else: continue container = traceable_matrix_crosstable() container += table container["traceables-matrix"] = matrix # backward = matrix.backward_relationship.capitalize() # forward = matrix.forward_relationship.capitalize() # container["relationships"] = (forward, backward) # container["boolean_matrix"] = 0#boolean_matrix # container["secondaries"] = matrix.secondaries return container
def gen_table(columns, data): table = nodes.table() tgroup = nodes.tgroup(cols=len(columns)) table += tgroup for column in columns: tgroup += nodes.colspec(colwidth=1) thead = nodes.thead() tgroup += thead headrow = nodes.row() for column in columns: entry = nodes.entry() para = nodes.paragraph() entry += para header = column.header() para += nodes.Text(header, header) headrow += entry thead += headrow tbody = nodes.tbody() tgroup += tbody for obj in data: row = nodes.row() for column in columns: entry = nodes.entry() para = nodes.paragraph() entry += para para += column.data(obj) row += entry tbody += row return [table]
def _description_table(self, descriptions, widths, headers): # generate table-root tgroup = nodes.tgroup(cols=len(widths)) for width in widths: tgroup += nodes.colspec(colwidth=width) table = nodes.table() table += tgroup # generate table-header thead = nodes.thead() row = nodes.row() for header in headers: entry = nodes.entry() entry += nodes.paragraph(text=header) row += entry thead += row tgroup += thead # generate table-body tbody = nodes.tbody() for desc in descriptions: row = nodes.row() for attr in desc: entry = nodes.entry() if not isinstance(attr, string_types): attr = str(attr) self.state.nested_parse(ViewList([attr], source=attr), 0, entry) row += entry tbody += row tgroup += tbody return table
def envy_resolve(app, doctree, fromdocname): objects = app.env.domaindata['envy']['objects'] # add uplink info for holder in doctree.traverse(uplink_placeholder): obj = objects[holder.name] links = [] for sp, pos, name, variants in obj.uplinks: signode = addnodes.desc_signature('', '') signode['first'] = False signode += make_refnode(app.builder, fromdocname, sp.docname, sp.iname + '-' + sp.name, addnodes.desc_addname(sp.name, sp.name), sp.name) text = ' {}: {}'.format(pos, name) signode += addnodes.desc_name(text, text) if variants is not None: text = ' [{}]'.format(variants) signode += addnodes.desc_annotation(text, text) links.append(signode) holder.replace_self(links) # add subnode list for holder in doctree.traverse(sub_placeholder): obj = objects[holder.name] add_variant = False for pos, name, child, variants in obj.subs: if variants is not None: add_variant = True table = nodes.table() headers = [(1, 'Address'), (1, 'Name'), (10, 'Description')] if add_variant: headers.insert(1, (1, 'Variants')) tgroup = nodes.tgroup(cols=len(headers)) table += tgroup for colwidth, header in headers: tgroup += nodes.colspec(colwidth=colwidth) thead = nodes.thead() tgroup += thead headrow = nodes.row() for colwidth, header in headers: entry = nodes.entry() para = nodes.paragraph() entry += para para += nodes.Text(header, header) headrow += entry thead += headrow tbody = nodes.tbody() tgroup += tbody for pos, name, child, variants in obj.subs: row = nodes.row() row += wrap_text_entry(pos) if add_variant: row += wrap_text_entry('all' if variants is None else variants) row += wrap_text_entry(name) entry = nodes.entry() para = nodes.paragraph() entry += para para += make_refnode(app.builder, fromdocname, child.docname, child.iname + '-' + child.name, nodes.Text(child.brief, child.brief), obj.brief) row += entry tbody += row holder.replace_self([table])
def create_list_table(self, matrix, options, docname): table = nodes.table() tgroup = nodes.tgroup(cols=2, colwidths="auto") table += tgroup # Add column specifications. tgroup += nodes.colspec(colwidth=50) tgroup += nodes.colspec(colwidth=50) # Add heading row. thead = nodes.thead() tgroup += thead row = nodes.row() thead += row entry = nodes.entry() row += entry backward_relationship = matrix.backward_relationship.capitalize() entry += nodes.paragraph(backward_relationship, backward_relationship) entry = nodes.entry() row += entry forward_relationship = matrix.forward_relationship.capitalize() entry += nodes.paragraph(forward_relationship, forward_relationship) # Add table body. tbody = nodes.tbody() tgroup += tbody for traceable in matrix.primaries: relatives = matrix.get_relatives(traceable) # Create first row with a first column. row = nodes.row() entry = nodes.entry(morerows=len(relatives) - 1) row += entry paragraph = nodes.paragraph() entry += paragraph paragraph += traceable.make_reference_node( self.app.builder, docname) for relative in relatives: if not row: # Create subsequent rows without a first column. row = nodes.row() tbody += row entry = nodes.entry() row += entry paragraph = nodes.paragraph() entry += paragraph paragraph += relative.make_reference_node( self.app.builder, docname) row = None return table
def process_indigo_option_nodes(app, doctree, fromdocname): env = app.builder.env for node in doctree.traverse(optionslist): content = [] tbl = nodes.table() tgroup = nodes.tgroup(cols=4) tbl += tgroup tgroup += nodes.colspec(colwidth=35) tgroup += nodes.colspec(colwidth=9) tgroup += nodes.colspec(colwidth=9) tgroup += nodes.colspec(colwidth=73) thead = nodes.thead() tgroup += thead row = nodes.row() thead += row row += createRowEntryText('Name') row += createRowEntryText('Type') row += createRowEntryText('Default') row += createRowEntryText('Short description') tbody = nodes.tbody() tgroup += tbody content.append(tbl) sorted_options = sorted(env.indigo_options, key=lambda o:o['name']) for opt_info in sorted_options: row = nodes.row() tbody += row # Create a reference newnode = nodes.reference('', '') innernode = nodes.Text(opt_info['name'], opt_info['name']) newnode['refdocname'] = opt_info['docname'] newnode['refuri'] = app.builder.get_relative_uri( fromdocname, opt_info['docname']) newnode['refuri'] += '#' + normalize_name(opt_info['name']) newnode.append(innernode) row += createRowEntry(newnode) row += createRowEntryText(opt_info['type']) row += createRowEntryText(opt_info['default']) row += createRowEntryText(opt_info['short']) node.replace_self(content)
def _build_markup(self, notifications): content = [] cols = ['Notification class', 'Payload class', 'Sample file link'] table = nodes.table() content.append(table) group = nodes.tgroup(cols=len(cols)) table.append(group) head = nodes.thead() group.append(head) for i in range(len(cols)): group.append(nodes.colspec(colwidth=1)) body = nodes.tbody() group.append(body) # fill the table header row = nodes.row() body.append(row) for col_name in cols: col = nodes.entry() row.append(col) text = nodes.strong(text=col_name) col.append(text) # fill the table content, one notification per row for name, payload, sample in notifications: row = nodes.row() body.append(row) col = nodes.entry() row.append(col) text = nodes.literal(text=name) col.append(text) col = nodes.entry() row.append(col) text = nodes.literal(text=payload) col.append(text) col = nodes.entry() row.append(col) ref = nodes.reference(refuri=self.LINK_PREFIX + self.SAMPLE_ROOT + sample) txt = nodes.inline() col.append(txt) txt.append(ref) ref.append(nodes.literal(text=sample)) return content
def format(self, app, docname, node, traceables, options): additional_attributes = options.get("attributes") or [] columns = ["tag", "title"] + additional_attributes table = nodes.table() table["classes"].append("traceables-listtable") tgroup = nodes.tgroup(cols=len(columns), colwidths="auto") table += tgroup # Add column specifications. for attribute_name in columns: tgroup += nodes.colspec(colwidth=1) # Add heading row. thead = nodes.thead() tgroup += thead row = nodes.row() thead += row for attribute_name in columns: entry = nodes.entry() row += entry container = nodes.container() entry += container text = attribute_name.capitalize() inline = nodes.inline(text, text) container += inline # Add table body. tbody = nodes.tbody() tgroup += tbody for traceable in traceables: row = nodes.row() tbody += row for attribute_name in columns: entry = nodes.entry() row += entry if attribute_name == "tag": inline = nodes.inline() inline += traceable.make_reference_node( app.builder, docname) elif attribute_name == "title": text = traceable.title if traceable.has_title else "" inline = nodes.inline(text, text) else: text = traceable.attributes.get(attribute_name, "") inline = nodes.inline(text, text) entry += inline return table
def _build_grade_listing(self, matrix, content): summarytitle = nodes.subtitle(text="Grades") content.append(nodes.raw(text="Grades", attributes={'tagname': 'h2'})) content.append(summarytitle) table = nodes.table() table.set_class("table") table.set_class("table-condensed") grades = matrix.grades tablegroup = nodes.tgroup(cols=2) summarybody = nodes.tbody() summaryhead = nodes.thead() for i in range(2): tablegroup.append(nodes.colspec(colwidth=1)) tablegroup.append(summaryhead) tablegroup.append(summarybody) table.append(tablegroup) content.append(table) header = nodes.row() blank = nodes.entry() blank.append(nodes.strong(text="Grade")) header.append(blank) blank = nodes.entry() blank.append(nodes.strong(text="Description")) header.append(blank) summaryhead.append(header) for grade in grades: item = nodes.row() namecol = nodes.entry() class_name = "label-%s" % grade.css_class status_text = nodes.paragraph(text=grade.title) status_text.set_class(class_name) status_text.set_class("label") namecol.append(status_text) item.append(namecol) notescol = nodes.entry() notescol.append(nodes.paragraph(text=grade.notes)) item.append(notescol) summarybody.append(item) return content
def build_table(self): table = nodes.table() tgroup = nodes.tgroup(cols=len(self.headers)) table += tgroup # TODO(sdague): it would be really nice to figure out how not # to have this stanza, it kind of messes up all of the table # formatting because it doesn't let tables just be the right # size. tgroup.extend( nodes.colspec(colwidth=col_width, colname='c' + str(idx)) for idx, col_width in enumerate(self.col_widths) ) thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node row_node.extend(nodes.entry(h, nodes.paragraph(text=h)) for h in self.headers) tbody = nodes.tbody() tgroup += tbody rows, groups = self.collect_rows() tbody.extend(rows) table.extend(groups) return table
def build_table_from_list(self, table_data, col_widths, header_rows, stub_columns): table = nodes.table() tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup for col_width in col_widths: colspec = nodes.colspec(colwidth=col_width) if stub_columns: colspec.attributes['stub'] = 1 stub_columns -= 1 tgroup += colspec rows = [] for row in table_data: row_node = nodes.row() for cell in row: entry = nodes.entry() entry += cell row_node += entry rows.append(row_node) if header_rows: thead = nodes.thead() thead.extend(rows[:header_rows]) tgroup += thead tbody = nodes.tbody() tbody.extend(rows[header_rows:]) tgroup += tbody return table
def run(self): if ValueTableDirective.values[0].description is None: list = nodes.bullet_list() for v in ValueTableDirective.values: item = nodes.list_item() item += nodes.literal(v.value, v.value) list += item return [list] table = nodes.table() tgroup = nodes.tgroup() tbody = nodes.tbody() for v in ValueTableDirective.values: row = nodes.row() entry = nodes.entry() entry += nodes.literal(v.value, v.value) row += entry entry = nodes.entry() entry += nodes.paragraph(text=v.description) row += entry tbody += row tgroup += nodes.colspec(colwidth=10) tgroup += nodes.colspec(colwidth=90) tgroup += tbody table += tgroup return [table]
def create_table(self, data, num_headers=1): table_node = nodes.table() if len(data) > 0: tgroup_node = nodes.tgroup(cols=len(data[0])) table_node += tgroup_node col_width = 100 // len(data[0]) for col_index in range(len(data[0])): colspec_node = nodes.colspec(colwidth=col_width) tgroup_node += colspec_node thead = nodes.thead() tgroup_node += thead tbody = nodes.tbody() tgroup_node += tbody for row_index, row in enumerate(data): row_node = nodes.row() for col_index, cell_item in enumerate(row): row_node += self.create_cell(col_index, cell_item, row_index < num_headers) if row_index < num_headers: thead += row_node else: tbody += row_node return table_node
def get_row(*column_texts): row = nodes.row('') for text in column_texts: node = nodes.paragraph('', '', nodes.Text(text)) row += nodes.entry('', node) return row
def run(self): ncolumns = self.options.get('columns', 2) node = nodes.Element() node.document = self.state.document self.state.nested_parse(self.content, self.content_offset, node) if len(node.children) != 1 or not isinstance(node.children[0], nodes.bullet_list): return [self.state.document.reporter.warning( '.. hlist content is not a list', line=self.lineno)] fulllist = node.children[0] # create a hlist node where the items are distributed npercol, nmore = divmod(len(fulllist), ncolumns) index = 0 table = nodes.table() tg = nodes.tgroup() table += tg row = nodes.row() tbody = nodes.tbody() for column in range(ncolumns): endindex = index + (column < nmore and (npercol + 1) or npercol) colspec = nodes.colspec() colspec.attributes['stub'] = 0 colspec.attributes['colwidth'] = 100. / ncolumns col = nodes.entry() col += nodes.bullet_list() col[0] += fulllist.children[index:endindex] index = endindex tg += colspec row += col tbody += row tg += tbody table['classes'].append('hlist') return [table]
def show_no_yaml_error(self): trow = nodes.row(classes=["no_yaml"]) trow += self.add_col("No yaml found %s" % self.yaml_file) trow += self.add_col("") trow += self.add_col("") trow += self.add_col("") return trow
def build_toc(descinfo, env): """Return a desc table of contents node tree""" separator = EMDASH child_ids = descinfo['children'] if not child_ids: return None max_fullname_len = 0 max_summary_len = 0 rows = [] for fullname, refid, summary in ichild_ids(child_ids, env): max_fullname_len = max(max_fullname_len, len(fullname)) max_summary_len = max(max_summary_len, len(summary)) reference_node = toc_ref(fullname, refid) ref_entry_node = entry('', paragraph('', '', reference_node)) sep_entry_node = entry('', paragraph('', separator)) sum_entry_node = entry('', paragraph('', summary)) row_node = row('', ref_entry_node, sep_entry_node, sum_entry_node) rows.append(row_node) col0_len = max_fullname_len + 2 # add error margin col1_len = len(separator) # no padding col2_len = max_summary_len + 10 # add error margin tbody_node = tbody('', *rows) col0_colspec_node = colspec(colwidth=col0_len) col1_colspec_node = colspec(colwidth=col1_len) col2_colspec_node = colspec(colwidth=col2_len) tgroup_node = tgroup('', col0_colspec_node, col1_colspec_node, col2_colspec_node, tbody_node, cols=3) return TocTable('', tgroup_node, classes=['toc'])
def collect_rows(self): rows = [] groups = [] try: # self.app.info("Parsed content is: %s" % self.yaml) for key, values in self.yaml: min_version = values.get('min_version', '') desc = values.get('description', '') classes = [] if min_version: desc += ("\n\n**New in version %s**\n" % min_version) min_ver_css_name = ("rp_min_ver_" + str(min_version).replace('.', '_')) classes.append(min_ver_css_name) trow = nodes.row(classes=classes) name = key if values.get('required', False) is False: name += " (Optional)" trow += self.add_col(name) trow += self.add_col(values.get('in')) trow += self.add_col(values.get('type')) trow += self.add_col(desc) rows.append(trow) except AttributeError as exc: if 'key' in locals(): self.app.warn("Failure on key: %s, values: %s. %s" % (key, values, exc)) else: rows.append(self.show_no_yaml_error()) return rows, groups
def _generate_rows(self, sensors): vendor_name = None for s in sensors: # only generate one row for each vendor name that serves as a group heading if 'vendor_name' in s and vendor_name != s['vendor_name']: vendor_name = s['vendor_name'] strong = nodes.strong(text=vendor_name) para = nodes.paragraph() para += strong entry = nodes.entry(morecols=5) entry += para row = nodes.row() row += entry yield row # then generate one row for each sensor yield self._row([ self._link(s.get('vendor_website', None), s.get('vendor_part_number', '')), ':ref:`{} <{}>`'.format(s.get('vendor_part_name', s.get('vendor_part_number', '')), s['url_name']), '``{}``'.format(s['name']), self._pretty_sensor_type(s['sensor_type']), self._auto_detect(s['name'], s['sensor_type']), ])
def create_table_row(self, row_cells): row = nodes.row() for cell in row_cells: entry = nodes.entry() row += entry entry += cell return row
def build_table_from_list(self, table_data, num_cols, col_widths, header_rows, stub_columns): table = nodes.table() tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup for col_width in col_widths: colspec = nodes.colspec(colwidth=col_width) if stub_columns: colspec.attributes['stub'] = 1 stub_columns -= 1 tgroup += colspec rows = [] for row in table_data: row_node = nodes.row() for cell_index, cell in enumerate(row): entry = nodes.entry() entry += cell row_node += entry if self.bias == "left" and not cell_index: remainder = num_cols - len(row) if remainder: entry["morecols"] = remainder if self.bias == "right" and cell_index == len(row) - 1: remainder = num_cols - (cell_index + 1) if remainder: entry["morecols"] = remainder rows.append(row_node) if header_rows: thead = nodes.thead() thead.extend(rows[:header_rows]) tgroup += thead tbody = nodes.tbody() tbody.extend(rows[header_rows:]) tgroup += tbody return table
def build_table(self, table_data): table = nodes.table() tgroup = nodes.tgroup(cols=len(self.headers)) table += tgroup tgroup.extend( nodes.colspec(colwidth=col_width, colname='c' + str(idx)) for idx, col_width in enumerate(self.col_widths) ) thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node row_node.extend(nodes.entry(h, nodes.paragraph(text=h)) for h in self.headers) tbody = nodes.tbody() tgroup += tbody rows, groups = self.get_rows(table_data) tbody.extend(rows) table.extend(groups) return table
def build_table_from_list(self, table_data, col_widths, header_rows, stub_columns): table = nodes.table() if self.widths == 'auto': table['classes'] += ['colwidths-auto'] elif self.widths: # "grid" or list of integers table['classes'] += ['colwidths-given'] tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup for col_width in col_widths: colspec = nodes.colspec() if col_width is not None: colspec.attributes['colwidth'] = col_width if stub_columns: colspec.attributes['stub'] = 1 stub_columns -= 1 tgroup += colspec rows = [] for row in table_data: row_node = nodes.row() for cell in row: entry = nodes.entry() entry += cell row_node += entry rows.append(row_node) if header_rows: thead = nodes.thead() thead.extend(rows[:header_rows]) tgroup += thead tbody = nodes.tbody() tbody.extend(rows[header_rows:]) tgroup += tbody return table
def append_row(*column_texts): row = nodes.row('') for text in column_texts: node = nodes.paragraph('') vl = ViewList() vl.append(text, '<autosummary>') state.nested_parse(vl, 0, node) row.append(nodes.entry('', node)) body.append(row)
def create_table_row(self, row_cells): row = nodes.row() for cell in row_cells: entry = nodes.entry() row += entry entry += nodes.paragraph(text=cell.strip()) return row
def build_table_row(*vals): rv = nodes.row('') for val in vals: if isinstance(val, nodes.Node): node = val else: node = nodes.paragraph(val, val) rv.append(nodes.entry(node, node)) return rv
def get_rows(self, table_data): rows = [] groups = [] trow = nodes.row() entry = nodes.entry() para = nodes.paragraph(text=unicode(table_data)) entry += para trow += entry rows.append(trow) return rows, groups
def _build_grade_listing(self, matrix, content): summarytitle = nodes.title(text="Grades") content.append(summarytitle) table = nodes.table() grades = matrix.grades tablegroup = nodes.tgroup(cols=2) summarybody = nodes.tbody() summaryhead = nodes.thead() for i in range(2): tablegroup.append(nodes.colspec(colwidth=1)) tablegroup.append(summaryhead) tablegroup.append(summarybody) table.append(tablegroup) content.append(table) header = nodes.row() blank = nodes.entry() blank.append(nodes.strong(text="Grade")) header.append(blank) blank = nodes.entry() blank.append(nodes.strong(text="Description")) header.append(blank) summaryhead.append(header) for grade in grades: item = nodes.row() namecol = nodes.entry() namecol.append(nodes.paragraph(text=grade.title)) item.append(namecol) notescol = nodes.entry() notescol.append(nodes.paragraph(text=grade.notes)) item.append(notescol) summarybody.append(item) return content
def _make_enum_documentation(self, obj): def get_entry(node): para = addnodes.compact_paragraph() para += node entry = nodes.entry() entry += para return entry desc = addnodes.desc_signature() desc['ids'].append(obj.get_id()) first = False desc += nodes.emphasis(text=u'enum') desc += nodes.Text(u' ') desc += addnodes.desc_name(text=obj.get_name()) desc.attributes['first'] = True content = addnodes.desc_content() if obj.brief(): para = nodes.paragraph() para += nodes.emphasis(text='Brief: ') para += nodes.Text(' '.join(obj.brief())) content += para table, body = nodes.table(), nodes.tbody() tgroup = nodes.tgroup(cols=3) thead = nodes.thead() for it in [20, 10, 70]: tgroup += nodes.colspec(colwidth=it) tgroup += thead tgroup += body table += tgroup head_row = nodes.row() for it in ['Name', 'Value', 'Brief']: head_row += get_entry(nodes.Text(it)) thead += head_row for val in sorted(obj.values): row = nodes.row() row += get_entry(nodes.literal(text=val.name)) tmp = [val.value if val.value is not None else '', ' '.join(val.brief())] for it in tmp: row += get_entry(nodes.Text(it)) body += row content += table return (desc, content)
def append_row(*column_texts): # type: (str) -> None row = nodes.row('') source, line = self.state_machine.get_source_and_line() for text in column_texts: node = nodes.paragraph('') vl = StringList() vl.append(text, '%s:%d:<autosummary>' % (source, line)) with switch_source_input(self.state, vl): self.state.nested_parse(vl, 0, node) try: if isinstance(node[0], nodes.paragraph): node = node[0] except IndexError: pass row.append(nodes.entry('', node)) body.append(row)
def prepare_table_header(titles, widths): """Build docutil empty table """ ncols = len(titles) assert len(widths) == ncols tgroup = nodes.tgroup(cols=ncols) for width in widths: tgroup += nodes.colspec(colwidth=width) header = nodes.row() for title in titles: header += nodes.entry('', nodes.paragraph(text=title)) tgroup += nodes.thead('', header) tbody = nodes.tbody() tgroup += tbody return nodes.table('', tgroup), tbody
def buildTableRowNode(self, row_data, classes=None): classes = [] if classes is None else classes row = nodes.row() for cell in row_data: if cell is None: continue cspan, rspan, cellElements = cell attributes = {"classes": classes} if rspan: attributes['morerows'] = rspan if cspan: attributes['morecols'] = cspan entry = nodes.entry(**attributes) entry.extend(cellElements) row += entry return row
def _create_row(self, *column_texts): row = nodes.row('') source, line = self.state_machine.get_source_and_line() for text_line in column_texts: node = nodes.paragraph('') vl = ViewList() for text in text_line.split('\n'): vl.append(text, '%s:%d' % (source, line)) with switch_source_input(self.state, vl): self.state.nested_parse(vl, 0, node) try: if isinstance(node[0], nodes.paragraph) and len(node.children) == 1: node = node[0] except IndexError: pass row.append(nodes.entry('', node)) return row
def build_row(row_data): """ Creates new rst table row node tree. Args: row_data (list): list of rst nodes with content of the row, length of the list should match number of columns in the table Returns: docutils.nodes.row: rst row node tree which contains given data """ row_node = nodes.row() # create entry nodes for data for content_nodes in row_data: entry_node = nodes.entry() row_node += entry_node for node in content_nodes: entry_node += node return row_node
def _append_row(self, body, column_texts): # type: (Any, str) -> None table_row = nodes.row('') source, line = self.state_machine.get_source_and_line() for text in column_texts: node = nodes.paragraph('') vl = ViewList() vl.append(text, f'{source}:{line}:<{self.name}>') with switch_source_input(self.state, vl): self.state.nested_parse(vl, 0, node) while len(node) > 0 and isinstance(node[0], nodes.paragraph): node = node[0] table_row.append(nodes.entry('', node)) body.append(table_row)
def gene_table(list2d, title=None, colwidths=None, rows_highlight=[], classes=[], _baseclass='neorg-gene-table', rows_highlight_class='neorg-gene-table-rows-highlight'): """ Generate table node from 2D list """ allclasses = [_baseclass] + classes if not list2d: table = nodes.table() table['classes'] += allclasses return table nrow = len(list2d) ncol = len(list2d[0]) if colwidths is None: colwidths = [1] * ncol table = nodes.table() tgroup = nodes.tgroup(cols=ncol) tbody = nodes.tbody() colspecs = [nodes.colspec(colwidth=cw) for cw in colwidths] rows = [nodes.row() for dummy in range(nrow)] if title: table += nodes.title(title, title) table += tgroup tgroup += colspecs tgroup += tbody tbody += rows for (row, list1d) in zip(rows, list2d): row += [gene_entry(elem) for elem in list1d] for (i, row) in enumerate(rows): if i in rows_highlight: row['classes'].append(rows_highlight_class) table['classes'] += allclasses return table
def build_row(item): """Return nodes.row with property description""" prop, propschema, required = item row = nodes.row() # Property row += nodes.entry('', nodes.paragraph(text=prop)) # Type str_type = type_description(propschema) par_type = nodes.paragraph() is_text = True for part in reClassDef.split(str_type): if part: if is_text: par_type += nodes.Text(part) else: par_type += addnodes.pending_xref( reftarget=part, reftype="class", refdomain=None, # py:class="None" py:module="altair" refdoc="user_guide/marks" refexplicit=False, refwarn=False ) par_type += nodes.literal(text = part,classes="xref py py-class") is_text = not is_text row += nodes.entry('', par_type) # Description md_parser = CommonMarkParser() str_descr = "***Required.*** " if required else "" str_descr += propschema.get('description', ' ') doc_descr = utils.new_document("schema_description") md_parser.parse(str_descr, doc_descr) row += nodes.entry('', *doc_descr.children) return row
def append_row(tbody, cells): row = nodes.row() tbody += row for cell in cells: entry = nodes.entry() row += entry try: if isinstance(cell, basestring): node = nodes.paragraph(text=cell) else: node = cell except NameError: if isinstance(cell, str): node = nodes.paragraph(text=cell) else: node = cell entry += node
def build_row(app, fromdocname, rowdata): row = nodes.row() for cell in rowdata: entry = nodes.entry() row += entry if isinstance(cell, list): for item in cell: if isinstance(item, dict): entry += process_cmd_node(app, item, fromdocname, '') else: entry += nodes.paragraph(text=item) elif isinstance(cell, bool): if cell: entry += nodes.paragraph(text="✔") entry['classes'] = ['coverage-ok'] else: entry += nodes.paragraph(text="✕") entry['classes'] = ['coverage-fail'] else: entry += nodes.paragraph(text=cell) return row
def get_filled_row(self, defect, columns, *args): """ Goes through each column and decides if it is there or prints empty cell. Args: defect (suds.sudsobject.mergedDefectDataObj): Defect object from suds. columns (list): List of column names (str). Returns: (nodes.row) Filled row node. """ row = nodes.row() for item_col in columns: item_col = item_col.upper() if item_col == 'CID': # CID is default and even if it is in disregard row += self.create_cell( str(defect['cid']), url=self.coverity_service.get_defect_url( self.stream, str(defect['cid']))) elif item_col == 'LOCATION': info = self.coverity_service.get_defect( str(defect['cid']), self.stream) linenum = info[-1]['defectInstances'][-1]['events'][-1][ 'lineNumber'] row += self.create_cell("{}#L{}".format( defect['filePathname'], linenum)) elif item_col in self.column_map: row += self.create_cell(defect[self.column_map[item_col]]) elif item_col in ('COMMENT', 'REFERENCE'): row += nodes.entry( '', self.create_paragraph_with_links( defect, self.defect_states_map[item_col], *args)) elif item_col in self.defect_states_map: row += self.cov_attribute_value_to_col( defect, self.defect_states_map[item_col]) else: # generic check which, if it is missing, prints empty cell anyway row += self.cov_attribute_value_to_col(defect, item_col) return row
def visit_enumerated_list(self, node): children = [] for child in node.children: if isinstance(child, nodes.list_item) and len(child.children): children.append(child) if not len(children): return suffix = self.list_suffix if self.list_suffix != None else '' self.list_level += 1 n = number('list' + str(self.list_level), self.project, self.storage) if n: if node.hasattr('ids'): for node_id in node['ids']: self.refs[node_id] = n newnode = nodes.table() newnode['classes'] = ['item-list'] tgroup = nodes.tgroup(cols=2) newnode += tgroup tbody = nodes.tbody() tgroup += tbody i = 0 for child in children: self.__process_list_in_children(child.children) trow = nodes.row() tbody += trow tentry1 = nodes.entry() trow += tentry1 tpar = nodes.paragraph(text=n + suffix) tpar['classes'] = ['item-list-number'] tentry1 += tpar tentry2 = nodes.entry() trow += tentry2 tentry2 += child.children i += 1 if i < len(children): n = number('list' + str(self.list_level), self.project, self.storage) node.replace_self(newnode) self.list_level -= 1
def collect_rows(self): rows = [] groups = [] try: # self.app.info("Parsed content is: %s" % self.yaml) for code, desc in self.yaml: h_code = http_code() h_code['code'] = code h_code['title'] = self.CODES.get(code, 'Unknown') trow = nodes.row() trow += self.add_col(h_code) trow += self.add_desc_col(desc) rows.append(trow) except AttributeError as exc: # if 'key' in locals(): self.app.warn("Failure on key: %s, values: %s. %s" % (code, desc, exc)) # else: # rows.append(self.show_no_yaml_error()) return rows, groups
def build_table_from_list(table_data, col_widths): table = nodes.table() tgroup = nodes.tgroup(cols=len(col_widths)) table += tgroup for col_width in col_widths: colspec = nodes.colspec(colwidth=col_width) tgroup += colspec rows = [] for row in table_data: row_node = nodes.row() for cell in row: entry = nodes.entry() entry += cell row_node += entry rows.append(row_node) thead = nodes.thead() thead.extend(rows[:1]) tgroup += thead tbody = nodes.tbody() tbody.extend(rows[1:]) tgroup += tbody return table
def collect_rows(self): # Add a column for a field. In order to have the RST inside # these fields get rendered, we need to use the # ViewList. Note, ViewList expects a list of lines, so chunk # up our content as a list to make it happy. def add_col(value): entry = nodes.entry() result = ViewList(value.split('\n')) self.state.nested_parse(result, 0, entry) return entry rows = [] groups = [] try: # self.app.info("Parsed content is: %s" % self.yaml) for key, values in self.yaml: min_version = values.get('min_version', '') desc = values.get('description', '') classes = [] if min_version: desc += ("\n\n**New in version %s**\n" % min_version) min_ver_css_name = ("rp_min_ver_" + str(min_version).replace('.', '_')) classes.append(min_ver_css_name) trow = nodes.row(classes=classes) name = key if values.get('optional') is True: name += " (Optional)" trow += add_col(name) trow += add_col(values.get('in')) trow += add_col(values.get('type')) trow += add_col(desc) rows.append(trow) except AttributeError as exc: self.app.warn("Failure on key: %s, values: %s. %s" % (key, values, exc)) raise return rows, groups
def get_rows(self, table_data): rows = [] groups = [] for row in table_data: sub_table_data = None if self.descend: for elem in row: if isinstance(elem, list): sub_table_data = row.pop(row.index(elem)) break trow = nodes.row() ncols = len(row) for idx, cell in enumerate(row): if self.spantolast and \ ncols < self.max_cols and idx == ncols - 1: morecols = self.max_cols - ncols entry = nodes.entry(morecols=morecols) else: entry = nodes.entry() para = nodes.paragraph(text=text_type(cell)) entry += para trow += entry if self.descend and sub_table_data: subtgroup = nodes.tgroup(cols=len(self.headers)) subtgroup.extend( nodes.colspec(colwidth=col_width, colname='c' + str(idx)) for idx, col_width in enumerate(self.col_widths)) subthead = nodes.thead() subtgroup += subthead subthead += trow subtbody = nodes.tbody() subtgroup += subtbody sub_rows, sub_groups = self.get_rows(sub_table_data) subtbody.extend(sub_rows) groups.append(subtgroup) groups.extend(sub_groups) else: rows.append(trow) return rows, groups
def make_row(entries): """ Make a row containing the supplied set of cell values (docutils nodes). To make a wide cell, enclose the docutils node in a (node, width) tuple. """ row = nodes.row() for node_width in entries: if isinstance(node_width, tuple): node, width = node_width else: node = node_width width = 1 if width == 1: entry = nodes.entry("", node) else: entry = nodes.entry("", node, morecols=width - 1) row += entry return row
def build_row(item): """Return nodes.row with property description""" prop, propschema, required = item row = nodes.row() # Property row += nodes.entry('', nodes.paragraph(text=prop), classes=["vl-prop"]) # Type str_type = type_description(propschema) par_type = nodes.paragraph() is_text = True for part in reClassDef.split(str_type): if part: if is_text: add_text(par_type, part) else: add_class_def(par_type, part) is_text = not is_text # row += nodes.entry('') row += nodes.entry('', par_type) #, classes=["vl-type-def"] # Description md_parser = CommonMarkParser() #str_descr = "***Required.*** " if required else "" str_descr = "" str_descr += propschema.get('description', ' ') doc_descr = utils.new_document("schema_description") md_parser.parse(str_descr, doc_descr) # row += nodes.entry('', *doc_descr.children, classes="vl-decsr") row += nodes.entry('', *doc_descr.children, classes=["vl-decsr"]) return row
def _make_table_body(self, types, data): body = nodes.tbody() if not data: return body ellipsis_column = -1 is_numeric = [False] * len(data[0]) for i, entry in enumerate(data[0]): if entry is Ellipsis: ellipsis_column = i if i > 0 and types[i - 1] is not Ellipsis: lt = stype2ltype[types[i - 1]] if lt == "int" or lt == "real": is_numeric[i] = True for datarow in data: row_node = nodes.row() body += row_node if datarow is Ellipsis: for i in range(len(data[0])): html_class = "row_index" if i == 0 else "hellipsis" text = "\u22F1" if i == ellipsis_column else "\u22EE" row_node += td_node(classes=[html_class], text=text) else: for i, text in enumerate(datarow): classes = [] if i == 0: classes = ["row_index"] text = comma_separated(int(text)) elif i == ellipsis_column: classes = ["vellipsis"] text = "\u2026" elif text is None: classes = ["na"] text = "NA" elif is_numeric[i]: text = text.replace("-", "\u2212") assert isinstance(text, str) row_node += td_node(classes=classes, text=text) return body
def create_options_table(content): tbl = nodes.table() tgroup = nodes.tgroup(cols=4) tbl += tgroup tgroup += nodes.colspec(colwidth=35) tgroup += nodes.colspec(colwidth=9) tgroup += nodes.colspec(colwidth=73) tgroup += nodes.colspec(colwidth=9) thead = nodes.thead() tgroup += thead row = nodes.row() thead += row row += create_row_entry_text('Name') row += create_row_entry_text('Type') row += create_row_entry_text('Short description') row += create_row_entry_text('Default') tbody = nodes.tbody() tgroup += tbody content.append(tbl) return tbody
def _get_row(self, obj): template = ":{}:`{} <{}>`\\ {}" if "nosignatures" in self.options: template = ":{}:`{} <{}>`" col1 = template.format("obj", obj.short_name, obj.name, escape("({})".format(obj.args))) col2 = obj.summary row = nodes.row("") for text in (col1, col2): node = nodes.paragraph("") view_list = ViewList() view_list.append(text, "<autosummary>") self.state.nested_parse(view_list, 0, node) try: if isinstance(node[0], nodes.paragraph): node = node[0] except IndexError: pass row.append(nodes.entry("", node)) return row
def run(self): """ Generate the definition list that displays the actual references. """ env = self.state.document.settings.env keys = env.domaindata['cite']['keys'] env.domaindata['cite']['refdoc'] = env.docname citations = env.domains['cite'].citations # TODO: implement #env.domaindata['cite']['refdocs'][env.docname] = Citations(env, path) tbody = nodes.tbody('') for i, key in enumerate(keys): row = nodes.row('') nid = "citation-%s" % nodes.make_id(key) row['classes'].append('footnote') row['ids'].append(nid) row['names'].append(nid) numcol = nodes.entry('', nodes.paragraph('', '[%d]' % (i + 1))) definition = self.get_reference_node(citations.get(key)) refcol = nodes.entry('', nodes.paragraph('', '', definition)) row.extend([numcol, refcol]) tbody.append(row) table_spec_node = addnodes.tabular_col_spec() table_spec_node['spec'] = 'cl' node = nodes.table( '', table_spec_node, nodes.tgroup('', nodes.colspec(colwidth=10, classes=['label']), nodes.colspec(colwidth=90), tbody)) return [node]
def collect_rows(self): rows = [] groups = [] try: # self.app.info("Parsed content is: %s" % self.yaml) for key, values in self.yaml: min_version = values.get('min_version', '') max_version = values.get('max_version', '') desc = values.get('description', '') classes = [] if min_version: desc += ("\n\n**New in version %s**\n" % min_version) min_ver_css_name = ("rp_min_ver_" + str(min_version).replace('.', '_')) classes.append(min_ver_css_name) if max_version: desc += ("\n\n**Deprecated in version %s**\n" % max_version) max_ver_css_name = ("rp_max_ver_" + str(max_version).replace('.', '_')) classes.append(max_ver_css_name) trow = nodes.row(classes=classes) name = key if values.get('required', False) is False: name += " (Optional)" trow += self.add_col(name) trow += self.add_col(values.get('in')) trow += self.add_col(values.get('type')) trow += self.add_col(desc) rows.append(trow) except AttributeError as exc: if 'key' in locals(): self.app.warn("Failure on key: %s, values: %s. %s" % (key, values, exc)) else: rows.append(self.show_no_yaml_error()) return rows, groups
def _generate_rows(self, motors): vendor_name = None for m in motors: # only generate one row for each vendor name that serves as a group heading if 'vendor_name' in m and vendor_name != m['vendor_name']: vendor_name = m['vendor_name'] strong = nodes.strong(text=vendor_name) para = nodes.paragraph() para += strong entry = nodes.entry(morecols=5) entry += para row = nodes.row() row += entry yield row # then generate one row for each sensor yield self._row([ self._link(m.get('vendor_website', None), m['vendor_part_number']), m['vendor_part_name'], '``{}``'.format(m['name']), m['motor_type'], self._auto_detect(m['name'], m['motor_type']), ])
def build_table(self): table = nodes.table() tgroup = nodes.tgroup(cols=len(self.header)) table += tgroup tgroup.extend( nodes.colspec(colwidth=col_width, colname="c" + str(idx)) for idx, col_width in enumerate(self.col_widths) ) thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node row_node.extend(nodes.entry(h, nodes.paragraph(text=h)) for h in self.header) tbody = nodes.tbody() tgroup += tbody rows, groups = self.collect_rows() tbody.extend(rows) table.extend(groups) return table
def buildTableFromFieldList(self, headerRows, stubColumns): table = nodes.table() tgroup = nodes.tgroup(cols=len(self.tableInfo[0])) table += tgroup for info in self.tableInfo[0]: colwidth = info['colwidth'] colspec = nodes.colspec(colwidth=colwidth) if stubColumns: colspec.attributes['stub'] = 1 stubColumns = stubColumns - 1 if not info['align'] is None: colspec.attributes['align'] = info['align'] if not info['more'] is None: colspec.attributes['more'] = info['more'] tgroup += colspec rows = [] for self.rowNum, row in enumerate(self.tableData): if self.definitionRow and self.rowNum == 0: continue rowNode = nodes.row() for self.colNum, cell in enumerate(row): info = self.tableInfo[self.rowNum][self.colNum] if info.get('isInColspan'): pass elif info.get('isFollowingRow'): pass else: entry = nodes.entry() if self.options.get('debug-cellinfo') in ['yes','1']: interesting = [ (1,'colNum'), (1,'rowNum'), (0,'colwidth'), (0,'columnId'), (0,'align'), (0,'more'), (1,'colspan'), (1,'rowspan'), (1,'columnIdRange'), (1,'columnIdRaw'), (1,'fieldNameRaw')] debugLines = [] for flag,k in interesting: if flag: debugLines.append('| %s=%s \n' % (k, info.get(k))) if debugLines: p = nodes.paragraph('', ''.join(debugLines)) entry += p entry += cell info = self.tableInfo[self.rowNum][self.colNum] morecols = info.get('colspan',1) - 1 if morecols: entry.attributes['morecols'] = morecols morerows = info.get('rowspan', 1) - 1 if morerows: entry.attributes['morerows'] = morerows align = info.get('align') if align: entry.attributes['align'] = align more = info.get('more') if more: entry.attributes['more'] = more rowNode += entry rows.append(rowNode) if headerRows: thead = nodes.thead() thead.extend(rows[:headerRows]) tgroup += thead tbody = nodes.tbody() tbody.extend(rows[headerRows:]) tgroup += tbody return table
def _grid_complex(self): node_tgroup = nodes.tgroup(cols=6) self.node_table += node_tgroup col_widths = [10, 10, 30, 30, 10, 10] for width in col_widths: node_colspec = nodes.colspec(colwidth=width) node_tgroup += node_colspec # HEAD row head_row = nodes.row(classes=['head']) self.node_tbody += head_row # HEAD left head_left_entry = nodes.entry(classes=['head_left'], morecols=1) head_left_entry += self.get_section('head_left') head_row += head_left_entry # HEAD mid head_entry = nodes.entry(classes=['head_center'], morecols=1) head_entry += self.get_section('head') head_row += head_entry # HEAD right head_right_entry = nodes.entry(classes=['head_right'], morecols=1) head_right_entry += self.get_section('head_right') head_row += head_right_entry # META row meta_row = nodes.row(classes=['meta']) self.node_tbody += meta_row # META left meta_left_entry = nodes.entry(classes=['meta'], morecols=2) meta_left_entry += self.get_section('meta_left') meta_row += meta_left_entry # META right meta_right_entry = nodes.entry(classes=['meta'], morecols=2) meta_right_entry += self.get_section('meta_right') meta_row += meta_right_entry # CONTENT row content_row = nodes.row(classes=['content']) self.node_tbody += content_row content_entry = nodes.entry(classes=['content'], morecols=5) content_entry.insert(0, self.node.children) content_row += content_entry # FOOTER row footer_row = nodes.row(classes=['footer']) self.node_tbody += footer_row # FOOTER left footer_left_entry = nodes.entry(classes=['footer_left'], morecols=1) footer_left_entry += self.get_section('footer_left') footer_row += footer_left_entry # FOOTER mid footer_entry = nodes.entry(classes=['footer'], morecols=1) footer_entry += self.get_section('footer') footer_row += footer_entry # FOOTER right footer_right_entry = nodes.entry(classes=['footer_right'], morecols=1) footer_right_entry += self.get_section('footer_right') footer_row += footer_right_entry # Construct table node_tgroup += self.node_tbody
def _grid_content(self, colwidths, side_left, side_right, footer): """ Creates most "content" based grid layouts. Side parts and footer can be activated via config. +------+---------+------+ | | Content | | | Side +---------+ Side | | | Footer | | +------+---------+------+ Only one active side is supported, as the section name is "side" for left and right section. :param colwidths: List of integer for column widths :param side_left: True or False :param side_right: True or False :param footer: True or False :return: need-table node """ side_morerows = 0 if footer: side_morerows = 1 # Table definition node_tgroup = nodes.tgroup(cols=len(colwidths)) self.node_table += node_tgroup for width in colwidths: node_colspec = nodes.colspec(colwidth=width) node_tgroup += node_colspec # CONTENT row content_row = nodes.row(classes=['content']) if side_left: side_entry = nodes.entry(classes=['side', 'left'], morerows=side_morerows) side_entry += self.get_section('side') content_row += side_entry content_entry = nodes.entry(classes=['content']) content_entry.insert(0, self.node.children) content_row += content_entry if side_right: side_entry = nodes.entry(classes=['side', 'right'], morerows=side_morerows) side_entry += self.get_section('side') content_row += side_entry # FOOTER row if footer: footer_row = nodes.row(classes=['footer']) footer_entry = nodes.entry(classes=['footer']) footer_entry += self.get_section('footer') footer_row += footer_entry # Construct table self.node_tbody += content_row if footer: self.node_tbody += footer_row node_tgroup += self.node_tbody
def _grid_simple(self, colwidths, side_left, side_right, footer): """ Creates most "simple" grid layouts. Side parts and footer can be activated via config. .. code-block:: text +------+---------+------+ | | Head | | | +---------+ | | | Meta | | | Side +---------+ Side | | | Content | | | +---------+ | | | Footer | | +------+---------+------+ Only one active side is supported, as the section name is "side" for left and right section. If ``side_right`` or ``side_left`` is set to ``partial``, the table grids looks like:: +------+------+------+ | | Head | | | Side +------+ Side | | | Meta | | +------+------+------+ | Content | +--------------------+ | Footer | +--------------------+ :param colwidths: List of integer for column widths :param side_left: False, 'full' or 'part' :param side_right: False, 'full' or 'part' :param footer: True or False :return: need-table node """ common_more_cols = 0 if side_left: if side_left == 'full': side_left_morerows = 2 else: side_left_morerows = 1 common_more_cols += 1 if footer: side_left_morerows += 1 if side_right: if side_right == 'full': side_right_morerows = 2 else: side_right_morerows = 1 common_more_cols += 1 if footer: side_right_morerows += 1 # Table definition node_tgroup = nodes.tgroup(cols=common_more_cols) self.node_table += node_tgroup for width in colwidths: node_colspec = nodes.colspec(colwidth=width) node_tgroup += node_colspec # HEAD row head_row = nodes.row(classes=['need', 'head']) if side_left: side_entry = nodes.entry(classes=['need', 'side'], morerows=side_left_morerows) side_entry += self.get_section('side') head_row += side_entry head_entry = nodes.entry(classes=['need', 'head']) head_entry += self.get_section('head') head_row += head_entry if side_right: side_entry = nodes.entry(classes=['need', 'side'], morerows=side_right_morerows) side_entry += self.get_section('side') head_row += side_entry # META row meta_row = nodes.row(classes=['need', 'meta']) meta_entry = nodes.entry(classes=['need', 'meta']) meta_entry += self.get_section('meta') meta_row += meta_entry # CONTENT row content_row = nodes.row(classes=['need', 'content']) content_entry = nodes.entry(classes=['need', 'content'], morecols=common_more_cols) content_entry.insert(0, self.node.children) content_row += content_entry # FOOTER row if footer: footer_row = nodes.row(classes=['need', 'footer']) footer_entry = nodes.entry(classes=['need', 'footer'], morecols=common_more_cols) footer_entry += self.get_section('footer') footer_row += footer_entry # Construct table self.node_tbody += head_row self.node_tbody += meta_row self.node_tbody += content_row if footer: self.node_tbody += footer_row node_tgroup += self.node_tbody
def process_audit_events(app, doctree, fromdocname): for node in doctree.traverse(audit_event_list): break else: return env = app.builder.env table = nodes.table(cols=3) group = nodes.tgroup( '', nodes.colspec(colwidth=30), nodes.colspec(colwidth=55), nodes.colspec(colwidth=15), ) head = nodes.thead() body = nodes.tbody() table += group group += head group += body row = nodes.row() row += nodes.entry('', nodes.paragraph('', nodes.Text('Audit event'))) row += nodes.entry('', nodes.paragraph('', nodes.Text('Arguments'))) row += nodes.entry('', nodes.paragraph('', nodes.Text('References'))) head += row for name in sorted(getattr(env, "all_audit_events", ())): audit_event = env.all_audit_events[name] row = nodes.row() node = nodes.paragraph('', nodes.Text(name)) row += nodes.entry('', node) node = nodes.paragraph() for i, a in enumerate(audit_event['args']): if i: node += nodes.Text(", ") node += nodes.literal(a, nodes.Text(a)) row += nodes.entry('', node) node = nodes.paragraph() backlinks = enumerate(sorted(set(audit_event['source'])), start=1) for i, (doc, label) in backlinks: if isinstance(label, str): ref = nodes.reference("", nodes.Text("[{}]".format(i)), internal=True) try: ref['refuri'] = "{}#{}".format( app.builder.get_relative_uri(fromdocname, doc), label, ) except NoUri: continue node += ref row += nodes.entry('', node) body += row for node in doctree.traverse(audit_event_list): node.replace_self(table)