"""Contains the manager classes that invoke the tables to generate."""__author__='Paul Landes'fromtypingimportSequence,Set,List,Dict,Iterable,Anyfromdataclassesimportdataclass,fieldimportsysimportloggingimportitertoolsasitfromitertoolsimportchainfromdatetimeimportdatetimefromioimportTextIOBaseimportpandasaspdfromzensols.configimportWritablefrom.importTablelogger=logging.getLogger(__name__)
def_get_table_rows(self,df:pd.DataFrame)->Iterable[List[Any]]:"""Return the rows/columns of the table given to :mod:``tabulate``."""cols=[tuple(map(lambdac:f'\\textbf{{{c}}}',df.columns))]returnit.chain(cols,map(lambdax:x[1].tolist(),df.iterrows()))def_get_tabulate_params(self)->Dict[str,Any]:params:Dict[str,Any]={'tablefmt':'latex_raw'}params.update(super()._get_tabulate_params())returnparamsdef_write_variable_content(self,name:str,value:Any,depth:int,writer:TextIOBase):self._write_line(f'\\newcommand{{\\{name}}}{{{value}}}',depth,writer)def_write_table_content(self,depth:int,writer:TextIOBase,content:List[str]):"""Write the text of the table's rows and columns."""forlix,lninenumerate(content[1:-1]):self._write_line(ln.strip(),depth,writer)if(lix-2)inself.hlines:self._write_line('\\hline',depth,writer)if(lix-2)inself.double_hlines:self._write_line('\\hline \\hline',depth,writer)
[docs]@dataclassclassSlackTable(LatexTable):"""An instance of the table that fills up space based on the widest column. """slack_column:int=field(default=0)"""Which column elastically grows or shrinks to make the table fit."""def__post_init__(self):super().__post_init__()self.uses.append('tabularx')@propertydefcolumns(self)->str:cols:str=self.column_alignsifcolsisNone:df:pd.DataFrame=self.formatted_dataframei:int=self.slack_columncols=('l'*(df.shape[1]-1))cols=cols[:i]+'X'+cols[i:]cols='|'+'|'.join(cols)+'|'returncols
[docs]@dataclassclassCsvToLatexTable(Writable):"""Generate a Latex table from a CSV file. """tables:Sequence[Table]=field()"""A list of table instances to create Latex table definitions."""package_name:str=field()"""The name Latex .sty package."""def_write_header(self,depth:int,writer:TextIOBase):date=datetime.now().strftime('%Y/%m/%d')writer.write("""\\NeedsTeXFormat{LaTeX2e}\\ProvidesPackage{%(package_name)s}[%(date)s Tables]"""%{'date':date,'package_name':self.package_name})uses:Set[str]=set(chain.from_iterable(map(lambdat:t.uses,self.tables)))foruseinsorted(uses):writer.write(f'\\usepackage{{{use}}}\n')iflen(uses)>0:writer.write('\n')
[docs]defwrite(self,depth:int=0,writer:TextIOBase=sys.stdout):"""Write the Latex table to the writer given in the initializer. """tlen:int=len(self.tables)self._write_header(depth,writer)fori,tableinenumerate(self.tables):try:table.write(depth,writer)exceptExceptionase:msg:str=f"could not format table '{table.name}': {e}"self._write_line(f'% erorr: {msg}',depth,writer)logger.error(msg,e)ifi<tlen:writer.write('\n')