This commit is contained in:
Mike Bloy 2023-10-28 19:41:40 -05:00
parent 8d9e4b4cb8
commit 4c98786f05
2 changed files with 56 additions and 26 deletions

View File

@ -1,5 +1,6 @@
import collections.abc import collections.abc
import csv import csv
from abc import ABC, abstractmethod
class DataCollection(collections.abc.Sequence): class DataCollection(collections.abc.Sequence):
@ -30,16 +31,48 @@ class DataCollection(collections.abc.Sequence):
self.data[name].append(d[name]) self.data[name].append(d[name])
class CSVParser(ABC):
def parse(self, filename):
records = []
with open(filename) as f:
rows = csv.reader(f)
headers = next(rows)
for row in rows:
records.append(self.make_record(headers, row))
return records
@abstractmethod
def make_record(self, headers, row):
pass
class DictCSVParser(CSVParser):
def __init__(self, types):
self.types = types
def make_record(self, headers, row):
return {name: func(val) for name, func, val in zip(headers, self.types, row)}
class InstanceCSVParser(CSVParser):
def __init__(self, cl):
self.cls = cl
def make_record(self, headers, row):
return self.cls.from_row(row)
def read_csv_as_dicts(filename, conversions): def read_csv_as_dicts(filename, conversions):
value = [] parser = DictCSVParser(conversions)
with open(filename) as f: records = parser.parse(filename)
rows = csv.reader(f) return records
headers = next(rows)
for row in rows:
value.append( def read_csv_as_instances(filename, cls):
{name: func(val) for name, func, val in zip(headers, conversions, row)} """Read a CSV file into a list of instances"""
) parser = InstanceCSVParser(cls)
return value records = parser.parse(filename)
return records
def read_csv_as_columns(filename, conversions): def read_csv_as_columns(filename, conversions):
@ -52,14 +85,3 @@ def read_csv_as_columns(filename, conversions):
{name: func(val) for name, func, val in zip(headers, conversions, row)} {name: func(val) for name, func, val in zip(headers, conversions, row)}
) )
return value return value
def read_csv_as_instances(filename, cls):
"""Read a CSV file into a list of instances"""
records = []
with open(filename) as f:
rows = csv.reader(f)
_ = next(rows)
for row in rows:
records.append(cls.from_row(row))
return records

View File

@ -1,12 +1,17 @@
class TableFormatter: from abc import ABC, abstractmethod
class TableFormatter(ABC):
@abstractmethod
def headings(self, headers): def headings(self, headers):
raise NotImplementedError() pass
@abstractmethod
def row(self, rowdata): def row(self, rowdata):
raise NotImplementedError() pass
class TextTableFormatter: class TextTableFormatter(TableFormatter):
def _printer(self, data): def _printer(self, data):
print(*("{: >10}".format(value) for value in data)) print(*("{: >10}".format(value) for value in data))
@ -18,7 +23,7 @@ class TextTableFormatter:
self._printer(rowdata) self._printer(rowdata)
class CSVTableFormatter: class CSVTableFormatter(TableFormatter):
def _printer(self, data): def _printer(self, data):
print(",".join(str(value) for value in data)) print(",".join(str(value) for value in data))
@ -29,7 +34,7 @@ class CSVTableFormatter:
return self._printer(rowdata) return self._printer(rowdata)
class HTMLTableFormatter: class HTMLTableFormatter(TableFormatter):
def _cell(self, value, tag): def _cell(self, value, tag):
return f"<{tag}>{value}</{tag}>" return f"<{tag}>{value}</{tag}>"
@ -57,6 +62,9 @@ def create_formatter(name):
def print_table(records, fields, formatter): def print_table(records, fields, formatter):
if not isinstance(formatter, TableFormatter):
raise TypeError("expected a TableFormatter")
formatter.headings(fields) formatter.headings(fields)
for record in records: for record in records:
formatter.row([getattr(record, fieldname) for fieldname in fields]) formatter.row([getattr(record, fieldname) for fieldname in fields])