def build_tables(self): """Test essential imports and show versions.""" caption = "Module Import Status" cols = "Module", "Description", "Status" rows = [] # This strange bit is needed because the ndscheduler package # is poorly implemented, and writes to stdout when it is loaded. stdout = sys.stdout sys.stdout = open(devnull, "w") for name, description in self.MODULES: try: import_module(name) status = Reporter.Cell("OK", classes="success center") except Exception as e: status = Reporter.Cell(str(e), classes="failure center") rows.append((name, description, status)) # Restore sanity to the world. sys.stdout = stdout tables = [Reporter.Table(rows, columns=cols, caption=caption)] caption = "Module Versions" cols = "Module", "Version" rows = [("Python", str(sys.version))] env = Environment() for key in sorted(env, key=str.lower): for package in env[key]: rows.append(str(package).split()) tables.append(Reporter.Table(rows, columns=cols, caption=caption)) return tables
def create_sheet(self): """Create and send an Excel report for the current SQL query.""" if self.sql: title = self.query or "Ad-hoc Query" report = Reporter(title, self.table, wrap=False) report.send("excel") else: self.show_form()
def columns(self): """ Create a sequence of column definitions for the output report. Number and types of columns depend on config parms. Return: Sequence of column definitions to add to object. """ return (Reporter.Column("Doc ID", width="70px"), Reporter.Column("Doc Title", width="200px"), Reporter.Column("Match", width="100px"), Reporter.Column("Context", width="200px"), Reporter.Column("Standard Wording?", width="50px"))
def build_tables(self): """Show the documents the user has locked.""" fields = "c.dt_out", "t.name", "d.id", "d.title" query = Query("usr u", *fields).order(*fields[:3]) query.join("checkout c", "c.usr = u.id") query.join("document d", "d.id = c.id") query.join("doc_type t", "t.id = d.doc_type") query.where("c.dt_in IS NULL") query.where(query.Condition("u.id", self.user.id)) rows = [] for dt_out, doc_type, doc_id, title in query.execute(self.cursor): doc_id = Reporter.Cell(doc_id, center=True) rows.append([str(dt_out)[:19], doc_type, doc_id, title]) caption = f"Checked out by {self.user.fullname or self.user.name}" return Reporter.Table(rows, caption=caption, columns=self.COLUMNS)
def plain_table(self): """Simplest report, showing all of the approval indications.""" if not hasattr(self, "_plain_table"): rows = [[indication] for indication in self.all_indications] cols = ["Full List of Drug Indications"] self._plain_table = Reporter.Table(rows, columns=cols) return self._plain_table
def build_tables(self): """Show the problems found in the manifest, if any.""" manifest_files = self.parse_manifest() client_files = self.gather_files() rows = sorted(self.find_errors(manifest_files, client_files)) caption = f"{len(rows):d} error(s) found" return Reporter.Table(rows, columns=self.COLNAMES, caption=caption)
def report(self): """This report is too specialized to use the base class version. Take off the buttons and add the banners/titles. If the user chooses the "by summary title" method for selecting which summary to use for the report, and the fragment supplied matches more than one summary document, display the form a second time so the user can pick the summary. """ # Make sure we have something to look for. if not self.terms: self.bail("At least one search term is required") # If the user wants an Excel workbook, create it. if self.format == "excel": return self.send_workbook() # Otherwise, assemble the options for an HTML report. if not hasattr(self, "_report"): opts = { "banner": "Standard Wording Report", "footer": self.footer, "subtitle": f"Report produced {date.today()}", "no_results": self.no_results, "page_opts": { "buttons": [], "session": self.session, "action": None, } } self._report = Reporter(self.title, self.tables, **opts) return self._report
def summary_table(self): """Table showing the totals for each status.""" if not hasattr(self, "_summary_table"): approved = rejected = unreviewed = 0 for audio_set in self.sets: approved += audio_set.approved rejected += audio_set.rejected unreviewed += audio_set.unreviewed row = [ Reporter.Cell(approved, center=True), Reporter.Cell(rejected, center=True), Reporter.Cell(unreviewed, center=True), ] opts = dict(columns=self.STATUSES, caption="Status Totals") self._summary_table = Reporter.Table([row], **opts) return self._summary_table
def table(self): """Object used to generate Excel or HTML output for the query.""" if not hasattr(self, "_table"): cols = self.excel_cols if self.request == "Excel" else self.cols opts = dict(columns=cols, sheet_name="Ad-hoc Query") self._table = Reporter.Table(self.rows, **opts) return self._table
def table(self): """Status counts table (or None if we have no matching documents).""" if not hasattr(self, "_table"): self._table = None if self.rows: opts = dict(caption=self.name, columns=self.COLUMNS) self._table = Reporter.Table(self.rows, **opts) return self._table
def build_tables(self): """Serve up the table.""" query = db.Query("session s", *self.FIELDS).order("s.last_act") query.join("usr u", "u.id = s.usr") query.where("s.ended IS NULL") rows = query.execute(self.cursor).fetchall() desc = self.cursor.description cols = [d[0].replace("_", " ").title() for d in desc] return Reporter.Table(rows, columns=cols)
def table(self): """Report table for this set.""" if not hasattr(self, "_table"): rows = [mp3.row for mp3 in self.audio_files] rows.append(self.subtotals) opts = dict(cols=self.COLUMNS, caption=self.name, classes="set") self._table = Reporter.Table(rows, **opts) return self._table
def rows(self): """Table rows for the report.""" if not hasattr(self, "_rows"): rows = [] root = self.doc.root for node in root.xpath(self.control.xpath, **self.XPATH_OPTS): parent = node.getparent() tag = parent.tag node_id = str(parent.get(self.CDR_ID)) row = ( Reporter.Cell(self.doc.cdr_id, center=True), self.doc.title, tag, Reporter.Cell(node_id, center=True), ) rows.append(row) self._rows = rows return self._rows
def table_by_board(self): """Create the 'by board' flavor of the report.""" boards = {} for meeting in self.meetings: if meeting.board.name not in boards: boards[meeting.board.name] = [meeting] else: boards[meeting.board.name].append(meeting) rows = [] for board in sorted(boards): if rows: rows.append(["\xA0"]) rows.append([Reporter.Cell(board, bold=True)]) for meeting in boards[board]: if meeting.canceled: meeting = Reporter.Cell(meeting, classes="strikethrough") rows.append([meeting]) return Reporter.Table(rows, caption=self.caption)
def rows(self): """Sequence of table rows (empty if we have no matching docs).""" if not hasattr(self, "_rows"): self._rows = [] if self.counts: for name in NewDocument.STATUSES: cell = Reporter.Cell(self.counts.get(name, 0), right=True) self._rows.append((name, cell)) return self._rows
def table(self): """Table of new documents (or None if there aren't any).""" if not hasattr(self, "_table"): self._table = None if self.docs: opts = dict(caption=self.name, columns=self.COLUMNS) rows = [doc.row for doc in self.docs] self._table = Reporter.Table(rows, **opts) return self._table
def table(self): """Create the table for the document's internal links.""" if not hasattr(self, "_table"): self._table = None if self.rows: caption = f"Links for CDR{self.doc.id} ({self.doc.title})" opts = dict(columns=self.COLUMNS, caption=caption) self._table = Reporter.Table(self.rows, **opts) return self._table
def html_row(self, summary_id, summary_title): """ Construct an HTML report row for this match Pass: summary_id - unique integer for the CDR summary document ID summary_title - string for the summary's title Return: sequence of column values for the report's row """ standard_wording = self.standard_wording and "Yes" or "No" return [ summary_id, summary_title, self.text, Reporter.Cell(self.span), Reporter.Cell(standard_wording, classes="center"), ]
def indication_table(self): """Group the report by approval indication.""" cols = "Approved Indication", "Drug Name", "Brand Name(s)" rows = [] for indication in sorted(self.indications, key=str.lower): drugs = sorted(self.indications[indication]) if len(drugs) > 1: name = Reporter.Cell(indication, rowspan=len(drugs)) else: name = indication for drug in drugs: link = Reporter.Table.B.A(drug.cdr_id, href=drug.url) span = Reporter.Table.B.SPAN(f"{drug.name} (", link, ")") if name: row = name, span, drug.brands or "" else: row = span, drug.brands or "" rows.append(row) name = None return Reporter.Table(rows, columns=cols, caption=self.caption)
def row(self): """Assemble the report row for this summary.""" if not hasattr(self, "_row"): self._row = [self.link, self.title] for markup_type in self.__control.types: count = self.__counts[markup_type] if count: self._row.append(Reporter.Cell(count, center=True)) else: self._row.append("") return self._row
def excel_cols(self): """Column names wrapped in `Reporter.Cell` objects. This lets us have some control over wrapping and column width. """ if not hasattr(self, "_excel_cols"): self._excel_cols = [] for col in self.cols: self._excel_cols.append(Reporter.Column(col, width="250px")) return self._excel_cols
def tables(self): """List with a single table for the HTML report.""" if not hasattr(self, "_tables"): opts = dict( banner=self.PAGE_TITLE, subtitle=self.subtitle, caption=self.caption, columns=self.columns, ) self._tables = [Reporter.Table(self.rows, **opts)] return self._tables
def subtotals(self): """Row in the report table for this set's subtotals.""" if not hasattr(self, "_subtotals"): subtotals = [] for status in Control.STATUSES: subtotals.append(f"{status}={self.counts.get(status[0], 0)}") subtotals = "\xa0 ".join(subtotals) language = self.control.language subtotals = f"{language} names in this set:\xa0 {subtotals}" cell = Reporter.Cell(subtotals, center=True, colspan=3) self._subtotals = [cell] return self._subtotals
def build_tables(self): parms = {SESSION: self.session, REQUEST: "View", "full": "full"} ids = [] rows = [] for doc in FilterSet.get_filters(self.session): parms[DOCID] = doc.cdr_id url = f"EditFilter.py?{urlencode(parms)}" id_cell = Reporter.Cell(doc.cdr_id, href=url) ids.append((doc.id, id_cell, doc.title)) rows.append((id_cell, doc.title)) columns = ( Reporter.Column("CDR ID", classes="id-col"), Reporter.Column("Filter Title", classes="title-col"), ) caption = f"{len(rows):d} CDR Filters (Sorted By Title)" opts = dict(caption=caption, columns=columns, id="titlesort") opts["logger"] = self.logger tables = [Reporter.Table(rows, **opts)] rows = [(deepcopy(row[1]), row[2]) for row in sorted(ids)] opts["caption"] = f"{len(rows):d} CDR Filters (Sorted By CDR ID)" opts["id"] = "idsort" tables.append(Reporter.Table(rows, **opts)) return tables
def table(self): """Report table for drugs of this action type.""" if not hasattr(self, "_table"): opts = dict( caption=self.caption, sheet_name=self.__type_name, columns=self.__control.columns, ) rows = [] for doc in sorted(self.docs): rows += doc.rows self._table = Reporter.Table(rows, **opts) return self._table
def build_tables(self): """Create the report tables the user requested. If none were requested, fall back to the form. """ tables = [] for agent_type in self.agent_types: query = self.create_query(agent_type) rows = [] for row in query.execute(self.cursor).fetchall(): query = self.Query("query_term_pub", "value") query.where(f"path = '{self.TYPE_PATH}'") query.where(query.Condition("doc_id", row.id)) types = query.execute(self.cursor).fetchall() types = ", ".join([t.value for t in types]) cells = [] if self.include_id: cells = [Reporter.Cell(row.id, center=True)] cells.append(row.title) cells.append(types) if self.include_fda_approval: cells.append("Yes" if row.accelerated else "") cells.append("Yes" if row.approved_in_children else "") if self.include_blank_column: cells.append("") rows.append(cells) caption = f"{self.AGENT_TYPES[agent_type]} ({len(rows)})" table = Reporter.Table(rows, columns=self.cols, caption=caption) if not self.show_gridlines: table.node.set("class", "no-gridlines") tables.append(table) if tables: return tables else: self.show_form()
def build_tables(self): if not self.types: self.show_form() cols = ["ID", "Summary"] for markup_type in self.TYPES: if markup_type in self.types: cols.append(markup_type.title()) query = db.Query("query_term t", "t.doc_id", "t.value").unique() query.join("query_term a", "a.doc_id = t.doc_id") query.where(f"t.path = '/{self.DOCTYPE}/Title'") query.where(f"a.path = '/{self.DOCTYPE}/DrugInfoMetaData/Audience'") query.where("a.value = 'Patients'") rows = query.order("t.value").execute(self.cursor).fetchall() summaries = [Summary(self, *row) for row in rows] rows = [summary.row for summary in summaries if summary.in_scope] return Reporter.Table(rows, columns=cols, caption=self.caption)
def drug_table(self): """Report grouping the information by drug.""" if self.include_brands: cols = "CDR ID", "Drug Name (Brand Name)", "Approved Indication(s)" else: cols = "CDR ID", "Drug Name", "Approved Indication(s)" rows = [] for drug in self.drugs: if self.include_brands and drug.brands: name = Reporter.Table.B.SPAN(drug.name, drug.brand_span) else: name = drug.name row = drug.link, name, drug.indications rows.append(row) return Reporter.Table(rows, columns=cols, caption=self.caption)
def row(self): """Table row for the report.""" if not hasattr(self, "_row"): ver_date = str(self.ver_date)[:10] if self.ver_date else "" self._row = ( Reporter.Cell(self.doc_id, center=True), self.doc_title, Reporter.Cell(self.cre_user, center=True), Reporter.Cell(str(self.cre_date)[:10], center=True), Reporter.Cell(ver_date, center=True), Reporter.Cell(self.ver_user, center=True), Reporter.Cell(self.pv, center=True), Reporter.Cell("Y" if self.epv else "N", center=True), ) return self._row
def cols(self): """Column headers selected to match the report options.""" if not hasattr(self, "_cols"): if self.include_headers: self._cols = [] if self.include_id: self._cols = ["CDR ID"] self._cols.append("Title") self._cols.append("Drug Type") if self.include_fda_approval: self._cols.append("Accelerated") self._cols.append("Approved in Children") if self.include_blank_column: self._cols.append(Reporter.Column("", width="300px")) else: self._cols = None return self._cols