def make_bom(): """Generate a bill of materials and return the tt object.""" finder = ModuleFinder() finder.run_script(sys.argv[0]) tt = ttable() tt.add_option(LONGTABLE) tt.add_head(['name', 'ver', 'path', 'lines', 'bytes', 'sha-1']) tt.set_col_alignments("lllrrl") for inc in [False, True]: for name, mod in sorted(finder.modules.items()): if system_module(mod) != inc: continue # don't use this one stats = file_stats(mod.__file__) ver = mod.globalnames.get('__version__', '---') if ver == 1 and name in sys.modules: # It has a version number; get it. try: ver = sys.modules[name].__version__ except AttributeError as e: ver = '---' fname = mod.__file__ if type(name) != str: name = "" if type(fname) != str: fname = "" tt.add_data([ latex_escape(name), ver, latex_escape(fname), stats[0], stats[1], stats[2] ]) tt.add_data(ttable.HR) return tt
def analyze_file(*,filename,mode=ttable.TEXT,verbose=False): """Analyze the named excel spreadsheet and return a string in the specified format.""" NL = tytable.line_end(mode) ret = [NL] # an array of strings to be joined and returned if mode==ttable.TEXT: ret += [filename,'\n',"="*len(filename),NL] elif mode==ttable.LATEX: ret += [textbf(latex_escape(filename+":")),NL] if filename.lower().endswith(".csv"): wb = load_csv_workbook(filename=filename) elif filename.lower().endswith(".xlsx"): try: wb = load_workbook(filename=filename, read_only=True) except zipfile.BadZipFile: ret += ['Cannot read; badZipFile',NL] return "".join(ret) except TypeError: ret += ['Cannot read; bad Excel File',NL] return "".join(ret) else: return "Cannot read file type: {}".format(filename) tt = ttable() tt.add_head(['Worksheet Name','rows with data','columns with data', 'total numeric values','cells with $>4$ sigfigs']) ret_worksheets = [] for ws in wb.worksheets: if verbose: print(f" Analyzing {os.path.basename(filename)} worksheet {ws.title}") sf_ws = SigFigStats() # for this worksheet empty_cells = 0 for row in ws.iter_rows(): for cell in row: if isinstance(cell,EmptyCell): empty_cells += 1 continue val = get_number(cell.value) if val!=None: sf_ws.add(val=val, row=cell.row, col=cell.column) ret_worksheets += ["Worksheet "+latex_escape(ws.title)] ret_worksheets += [sf_ws.typeset(mode=mode)] ret_worksheets += ["rows: {} columns: {} numbers: {}".format(sf_ws.max_row,sf_ws.max_col,sf_ws.count)] ret_worksheets += [""] tt.add_data([latex_escape(ws.title),sf_ws.max_row,sf_ws.max_col,sf_ws.count, sf_ws.improper_count()]) # End of worksheet processing tt.set_col_totals([3,4]) ret += [tt.typeset(mode=mode)] + [NL] + ret_worksheets # count the number of numbers and their precision return NL.join(ret)
def analyze_xlsx(*,filename,mode=TEXT): """Analyze the named excel spreadsheet and return a string in the specified format.""" ret = [] # an array of strings to be joined and returned NL = tytable.line_end(mode) if mode==TEXT: ret += [filename,'\n',"="*len(filename),NL] elif mode==LATEX: ret += [textbf(latex_escape(filename+":")),NL] try: wb = load_workbook(filename=filename, read_only=True) except zipfile.BadZipFile: ret += ['Cannot read; badZipFile',NL] return "".join(ret) except TypeError: ret += ['Cannot read; bad Excel File',NL] return "".join(ret) tt = ttable() tt.add_head(['','Worksheet Name','rows with data','columns with data', 'total numeric values','cells with $>4$ sigfigs']) sb = SigFigStats() # for all the worksheets for i in range(len(wb.worksheets)): ws = wb.worksheets[i] wssb = SigFigStats() # for this worksheet improper_count = 0 for row in ws.iter_rows(): for cell in row: if isinstance(cell,EmptyCell): continue try: if cell.value==None: continue val = float(cell.value) except (ValueError,TypeError,OverflowError) as e: continue if improperly_rounded(val): sb.add(val=val, row=cell.row+1, col=cell.column+1) wssb.add(val=val, row=cell.row+1, col=cell.column+1) improper_count += 1 tt.add_data([i+1,latex_escape(ws.title),wssb.max_row,wssb.max_col,wssb.count, improper_count]) # End of worksheet processing tt.add_data(tt.HR) tt.add_data(['total','--','--','--',sb.count]) ret += [tt.typeset(mode=mode)] ret += [sb.typeset(mode=mode)] # count the number of numbers and their precision ret.append(NL) return "\n".join(ret)
def typeset_cell(self, formatted_value, col_number): """Typeset a value for a given column number.""" import math align = self.col_alignment.get(col_number, self.LEFT) if self.mode == self.HTML: return formatted_value if self.mode == self.LATEX: if self.OPTION_NO_ESCAPE in self.options: return formatted_value else: return latex_tools.latex_escape(formatted_value) if self.mode == self.TEXT: try: fill = (self.col_formatted_widths[col_number] - len(formatted_value)) except IndexError: fill = 0 if align == self.RIGHT: return " " * fill + formatted_value if align == self.CENTER: return " " * math.ceil( fill / 2.0) + formatted_value + " " * math.floor( fill / 2.0) # Must be LEFT if col_number != self.cols - 1: # not the last column return formatted_value + " " * fill return formatted_value # don't indent last column
def analyze_csv(*,filename,mode=TEXT): """Analyze the numbers in a text file""" ret = [] NL = tytable.line_end(mode) if mode==TEXT: ret += [filename,'\n',"="*len(filename),NL] elif mode==LATEX: ret += [textbf(latex_escape(filename+":")),NL] div = re.compile("[ ,]") sb = SigFigStats() with open(filename,"r") as f: row_number = 0 for line in f: row_number += 1 col_number = 0 for word in div.split(line): try: val = float(word) sb.add(val=val,row=row_number,col=col_number) except (ValueError,TypeError,OverflowError) as e: pass col_number += 1 ret += ["rows: {} columns: {} numbers: {}".format(sb.max_row,sb.max_col,sb.count),NL] ret += [sb.typeset(mode=mode)] return "\n".join(ret)
def write_tail(doc, f, tail=None): if tail is None: tail = doc.tail if tail is not None: if hasattr(doc, 'option') and doc.option(OPTION_NO_ESCAPE): f.write(latex_escape(tail)) else: f.write(tail)
def write_text(doc, f, text=None): if text is None: text = doc.text if text is not None: if hasattr(doc, 'option') and doc.option(OPTION_NO_ESCAPE): f.write(latex_escape(text)) else: f.write(text)
def typeset(self, *, mode=None, option=None, out=None): """ Returns the typeset output of the entire table. Builds it up in """ if (self.OPTION_LONGTABLE in self.options) and (self.OPTION_TABULARX in self.options): raise RuntimeError("OPTION_LONGTABLE and OPTION_TABULARX conflict") if len(self.data) == 0: print("typeset: no rows") return "" if mode: self.set_mode(mode) if self.mode not in [self.TEXT, self.LATEX, self.HTML]: raise ValueError("Invalid typesetting mode " + self.mode) if option: self.add_option(option) print("add option", option) self.cols = self.ncols() # cache if self.cols == 0: print("typeset: no data") return "" if self.mode not in [self.TEXT, self.LATEX, self.HTML]: raise ValueError("Invalid typesetting mode " + self.mode) if self.mode not in [self.TEXT, self.LATEX, self.HTML]: raise ValueError("Invalid typesetting mode " + self.mode) ret = [""] # array of strings that will be concatenatted # If we need column totals, compute them if hasattr(self, "col_totals"): self.compute_and_add_col_totals() # Precalc any table widths if necessary if self.mode == self.TEXT: self.calculate_col_formatted_widths() if self.title: ret.append(self.title + ":" + "\n") # # Start of the table # if self.mode == self.LATEX: if self.fontsize: ret.append("{\\fontsize{%d}{%d}\\selectfont" % (self.fontsize, self.fontsize + 1)) try: colspec = self.latex_colspec except AttributeError: colspec = "r" * self.cols if self.OPTION_LONGTABLE not in self.options: # Regular table if self.OPTION_TABLE in self.options: ret.append("\\begin{table}") if self.OPTION_CENTER in self.options: ret.append("\\begin{center}") if self.caption: ret += ["\\caption{", self.caption, "}\n"] if self.label: ret.append("\\label{") ret.append(self.label) ret.append("}") if self.OPTION_TABULARX in self.options: ret += ["\\begin{tabularx}{\\textwidth}{", colspec, "}\n"] else: ret += ["\\begin{tabular}{", colspec, "}\n"] ret += self.typeset_headings() if self.OPTION_LONGTABLE in self.options: # Longtable ret += ["\\begin{longtable}{", colspec, "}\n"] if self.caption: ret += ["\\caption{", self.caption, "}\\\\ \n"] if self.label: ret += ["\\label{", self.label, "}"] ret += self.typeset_headings() ret.append("\\hline\\endfirsthead\n") if self.label: ret += [r'\multicolumn{', str(self.ncols()), r'}{c}{(Table \ref{', self.label, r'} continued)}\\', '\n'] ret += self.typeset_headings() ret.append("\\hline\\endhead\n") ret += ['\\multicolumn{', str(self.ncols()), '}{c}{(Continued on next page)}\\\\ \n'] ret.append(self.footer) ret.append("\\hline\\endfoot\n") ret.append(self.footer) ret.append("\\hline\\hline\\endlastfoot\n") elif self.mode == self.HTML: ret.append("<table>\n") ret += self.typeset_headings() elif self.mode == self.TEXT: if self.caption: ret.append("================ {} ================\n".format(self.caption)) if self.header: ret.append(self.header) ret.append("\n") ret += self.typeset_headings() # # typeset each row. # computes the width of each row if necessary # for row in self.data: # See if we should omit this row if self.should_omit_row(row): continue # See if this row demands special processing if row.data == self.HR: ret.append(self.typeset_hr()) continue ret.append(self.typeset_row(row)) # # End of the table ## if self.mode == self.LATEX: if self.OPTION_LONGTABLE not in self.options: if self.OPTION_TABULARX in self.options: ret.append("\\end{tabularx}\n") else: ret.append("\\end{tabular}\n") if self.OPTION_CENTER in self.options: ret.append("\\end{center}") if self.OPTION_TABLE in self.options: ret.append("\\end{table}") else: ret.append("\\end{longtable}\n") if self.fontsize: ret.append("}") if self.footnote: ret.append("\\footnote{") ret.append(latex_tools.latex_escape(self.footnote)) ret.append("}") elif self.mode == self.HTML: ret.append("</table>\n") elif self.mode == self.TEXT: if self.footer: ret.append(self.footer) ret.append("\n") # Finally, add any variables that have been defined for (name, value) in self.variables.items(): if self.mode == self.LATEX: ret += latex_var(name, value) if self.mode == self.HTML: ret += "".join(["Note: ", name, " is ", value, "<br>"]) outbuffer = "".join(ret) if out: out.write(outbuffer) return outbuffer
def latex_cell_text(self, cell): if self.option(OPTION_NO_ESCAPE): return cell.text else: return latex_escape(cell.text)