2024-02-04 10:28:09 -06:00

64 lines
1.6 KiB
Python

from abc import ABC, abstractmethod
class TableFormatter(ABC):
_formats = {}
@classmethod
def __init_subclass__(cls):
name = cls.__module__.split('.')[-1]
TableFormatter._formats[name] = cls
@abstractmethod
def headings(self, headers):
pass
@abstractmethod
def row(self, rowdata):
pass
class ColumnFormatMixin:
formats = []
def row(self, rowdata):
rowdata = [(fmt % d) for fmt, d in zip(self.formats, rowdata)]
super().row(rowdata)
class UpperHeadersMixin:
def headings(self, headers):
super().headings([h.upper() for h in headers])
def create_formatter(name, column_formats=None, upper_headers=False):
if not name:
raise ValueError(f'formatter named "{name}" not implemented')
if name not in TableFormatter._formats:
__import__(f'{__package__}.{name}')
formatter = TableFormatter._formats.get(name)
if not formatter:
raise RuntimeError(f'Unknown format {name}')
if upper_headers:
class _UpperFormatter(UpperHeadersMixin, formatter):
pass
formatter = _UpperFormatter
if column_formats:
class _ColumnFormatter(ColumnFormatMixin, formatter):
formats = column_formats
formatter = _ColumnFormatter
return formatter()
def print_table(records, fields, formatter):
if not isinstance(formatter, TableFormatter):
raise TypeError("expected a TableFormatter")
formatter.headings(fields)
for record in records:
formatter.row([getattr(record, fieldname) for fieldname in fields])