def move_footer(app, doctree): if doctree.traverse(footer_topic): dec = nodes.decoration() doctree.append(dec) for f1 in doctree.traverse(footer_topic): dec.append(f1.deepcopy()) f1.parent.remove(f1)
def apply(self): header = self.generate_header() footer = self.generate_footer() if header or footer: decoration = nodes.decoration() decoration += header decoration += footer document = self.document index = document.first_child_not_matching_class( nodes.PreDecorative) if index is None: document += decoration else: document[index:index] = [decoration]
def on_missing_reference(app, env, node, contnode): # Resolver for interrogate classes that supports either snake case or camel # case naming. Depending on the variation that is active, it will link to # either the Python or C++ reference as appropriate. target = node['reftarget'] # Figure out which part is the module and which part is the class. prefix = '' module = 'panda3d.core' if target.startswith('panda3d.'): parts = target.split('.', 2) if len(parts) == 2: # It's trying to resolve a reference to a module; we can't help # with that. return module = '.'.join(parts[:2]) prefix = module + '.' target = '.'.join(parts[2:]) else: # Something like .core.NodePath, perhaps? modpart = target.split('.', 1)[0] if idb.has_module('panda3d.' + modpart): module = 'panda3d.' + modpart prefix = modpart + '.' target = target.split('.', 1)[1] variation = getattr(env.app.builder, 'current_variation', None) if variation and variation[0] == 'cpp': domain = env.domains['cpp'] else: domain = env.domains['py'] resolved = target and resolve_reference(target, module, domain=domain.name) typ = node['reftype'] if domain.name == 'cpp' and typ == 'meth': # C++ domain doesn't have "meth", everything is "func" there. typ = 'func' if resolved and (resolved[0] == typ or typ == 'obj'): refdoc = node.get('refdoc', env.docname) # Try to match the original, but with the canonical mangling # (depending on Python versus C++) if len(contnode.children) and not node.get('refexplicit'): oldtext = contnode.children[0].astext() if domain.name == 'cpp': text = resolved[1] text = '::'.join( text.split('::')[-oldtext.replace('.', '::').count('.') - 1:]) else: text = prefix + resolved[1] text = '.'.join(text.split('.')[-oldtext.count('.') - 1:]) if oldtext.endswith("()"): text += "()" contnode.children[0] = nodes.Text(text) elif domain.name == 'cpp': # Work around a bug in the C++ resolver, which expects this # text node to be the child of an Element. I picked a # decoration element since it happens not to translate to # anything (not sure what its purpose is). if isinstance(contnode, nodes.Text): contnode = nodes.decoration('', contnode) # C++ references don't have a module prefix and use :: for scoping if domain.name == 'cpp': target = resolved[1] if typ == 'obj': # Another bug workaround typ = resolved[0] if typ in ('enum', 'class', 'struct', 'union') and resolved[0] == 'type': # Squelch warning typ = resolved[0] else: target = prefix + resolved[1] return domain.resolve_xref(env, refdoc, app.builder, typ, target, node, contnode)
def doctree_factory(report, fmt='html'): ''' Takes a report and builds an adequated doctree for it ''' report = report[0] # Create the doctree and set the document title doctree = new_document('<string>') doctree.setdefault('title', report.title) # Report's main title doctree.append(title(text=report.title)) # Setup header and footer doc_decoration = decoration() doc_header = header() doc_header.append(paragraph(text=report.title)) doc_decoration.append(doc_header) doc_footer = footer() date_str = date.today().strftime("%d/%m/%Y") doc_footer.append(paragraph(text=date_str)) doc_decoration.append(doc_footer) doctree.append(doc_decoration) # Report's description s_description = section() doc_desc_title = paragraph() doc_desc_title.append(strong(text=_('Description'))) s_description.append(doc_desc_title) s_description.append(paragraph(text=report.description)) doctree.append(s_description) # List of active filters if report.filters: s_filters = section() doc_filters_title = paragraph() doc_filters_title.append(strong(text=_('Active Filters'))) s_filters.append(doc_filters_title) filters_list = bullet_list(bullet='*') for filt in report.filters: l_item = list_item() filt_text = '%s %s %s' % ((filt[0],) + filt[2:4]) l_item.append(paragraph(text=filt_text)) filters_list.append(l_item) s_filters.append(filters_list) doctree.append(s_filters) # Data table(s) # If there are no groupings, show one table with all (filtered) data if not report.groupings: s_table = section() t_table = table() t_group = tgroup() t_group.setdefault('cols', len(report.columns)) for col in report.columns: cspec = colspec() cspec.setdefault('colwidth', int(col['width'])) t_group.append(cspec) t_head = thead() t_head_row = row() for col in report.columns: c_entry = entry() c_entry.append(paragraph(text=col['title'])) t_head_row.append(c_entry) t_head.append(t_head_row) t_group.append(t_head) t_body = tbody() for r_row in report.rows: t_row = row() for r_cell in r_row: t_entry = entry() if r_cell['type'] == 'object': t_entry.append(paragraph(text=r_cell['obj'])) elif r_cell['type'] == 'iterable': objects_list = bullet_list(bullet='*') for element in r_cell['obj']: ol_item = list_item() c_item = paragraph(text=element) ol_item.append(paragraph(text=element)) objects_list.append(ol_item) t_entry.append(objects_list) t_row.append(t_entry) t_body.append(t_row) # Aggregations if report.has_aggregations: t_row = row() for aggr in report.aggregations: t_entry = entry() if aggr: t_entry.append(paragraph(text='%.2f (%s)' % (aggr))) t_row.append(t_entry) t_body.append(t_row) t_group.append(t_body) t_table.append(t_group) s_table.append(t_table) doctree.append(s_table) else: # If there are groups, setup a table for every group. # Also, add a list of groupings. s_groups_list = section() doc_groups_title = paragraph() doc_groups_title.append(strong(text=_('Active Groupings'))) s_groups_list.append(doc_groups_title) groups_list = bullet_list(bullet='*') for r_group in report.groupings: l_item = list_item() l_item.append(paragraph(text=r_group.capitalize())) groups_list.append(l_item) s_groups_list.append(groups_list) doctree.append(s_groups_list) for r_group in report.groupings: # Dummy paragraph for spacing s_table = section() s_table.append(paragraph()) if len(report.groupings) > 1: s_table.append( paragraph( text=_('Grouped By') + ' %s' % r_group.capitalize() ) ) for ind, choice in getattr( report, 'grouping_choices_%s' % r_group ): # Table group title p_table_title = paragraph() p_table_title.append(strong(text=choice)) s_table.append(p_table_title) t_table = table() t_group = tgroup() t_group.setdefault('cols', len(report.columns)) for col in report.columns: cspec = colspec() cspec.setdefault('colwidth', int(col['width'])) t_group.append(cspec) t_head = thead() t_head_row = row() for col in report.columns: c_entry = entry() c_entry.append(paragraph(text=col['title'])) t_head_row.append(c_entry) t_head.append(t_head_row) t_group.append(t_head) t_body = tbody() group_rows = getattr(report, 'rows_%s' % choice) for g_row in group_rows: t_row = row() for r_cell in r_row: t_entry = entry() if r_cell['type'] == 'object': t_entry.append(paragraph(text=r_cell['obj'])) elif r_cell['type'] == 'iterable': objects_list = bullet_list(bullet='*') for element in r_cell['obj']: ol_item = list_item() c_item = paragraph(text=element) ol_item.append(c_item) objects_list.append(ol_item) t_entry.append(objects_list) t_row.append(t_entry) t_body.append(t_row) t_row = row() for r_cell in g_row: t_entry = entry() t_entry.append(paragraph(text=r_cell)) t_row.append(t_entry) t_body.append(t_row) # Aggregations if report.aggregations: t_row = row() for aggr in getattr(report, 'aggregations_%s' % choice): t_entry = entry() if aggr and aggr[0]: t_entry.append( paragraph(text='%.2f (%s)' % (aggr)) ) t_row.append(t_entry) t_body.append(t_row) t_group.append(t_body) t_table.append(t_group) s_table.append(t_table) doctree.append(s_table) if report.aggregations: summary = section() summary.append(paragraph()) p_summary_title = paragraph() p_summary_title.append(strong(text=_('Summary'))) summary.append(p_summary_title) st_table = table() st_group = tgroup() st_group.setdefault('cols', len(report.columns)) for col in report.columns: cspec = colspec() cspec.setdefault('colwidth', int(col['width'])) st_group.append(cspec) st_head = thead() st_head_row = row() for c in report.columns: c_entry = entry() c_entry.append(paragraph(text=c['title'])) st_head_row.append(c_entry) st_head.append(st_head_row) st_group.append(st_head) st_body = tbody() st_row = row() for aggr in report.aggregations: st_entry = entry() if aggr: st_entry.append(paragraph(text='%.2f (%s)' % (aggr))) st_row.append(st_entry) st_body.append(st_row) st_group.append(st_body) st_table.append(st_group) summary.append(st_table) doctree.append(summary) # Charts Handling # odt writer support for external images is not working if report.charts and fmt != 'odt': s_charts = section() p_charts_title = paragraph() charts_title = strong(text=_('Charts')) p_charts_title.append(charts_title) s_charts.append(p_charts_title) for chart in report.charts: s_chart = section() p_chart_title = paragraph(text=chart['field'].capitalize()) s_chart.append(p_chart_title) i_chart = image( uri=chart['uri'], width='70%', ) s_chart.append(i_chart) s_charts.append(s_chart) doctree.append(s_charts) return doctree