# tableformat.py class TableFormatter(object): def headings(self, headers): ''' Emit the table headers ''' raise NotImplementedError() def row(self, rowdata): ''' Emit a single row of table data ''' raise NotImplementedError() class TextTableFormatter(TableFormatter): ''' Output data in plain-text format. ''' def headings(self, headers): for h in headers: print(f'{h:>10s}', end=' ') print() print(('-'*10 + ' ')*len(headers)) def row(self, rowdata): for d in rowdata: print(f'{d:>10s}', end=' ') print() class CSVTableFormatter(TableFormatter): ''' Output data in CSV format. ''' def headings(self, headers): print(','.join(headers)) def row(self, rowdata): print(','.join(rowdata)) class HTMLTableFormatter(TableFormatter): ''' Output data in HTML format. ''' def headings(self, headers): print('', end='') for h in headers: print(f'{h}', end='') print('') def row(self, rowdata): print('', end='') for d in rowdata: print(f'{d}', end='') print('') class FormatError(Exception): pass def create_formatter(name): ''' Create an appropriate formatter given an output format name ''' if name == 'txt': return TextTableFormatter() elif name == 'csv': return CSVTableFormatter() elif name == 'html': return HTMLTableFormatter() else: raise FormatError(f'Unknown table format {name}') def print_table(objects, columns, formatter): ''' Make a nicely formatted table from a list of objects and attribute names. ''' formatter.headings(columns) for obj in objects: rowdata = [ str(getattr(obj, name)) for name in columns ] formatter.row(rowdata)