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 csv
from abc import ABC, abstractmethod
class DataCollection(collections.abc.Sequence):
@ -30,16 +31,48 @@ class DataCollection(collections.abc.Sequence):
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):
value = []
with open(filename) as f:
rows = csv.reader(f)
headers = next(rows)
for row in rows:
value.append(
{name: func(val) for name, func, val in zip(headers, conversions, row)}
)
return value
parser = DictCSVParser(conversions)
records = parser.parse(filename)
return records
def read_csv_as_instances(filename, cls):
"""Read a CSV file into a list of instances"""
parser = InstanceCSVParser(cls)
records = parser.parse(filename)
return records
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)}
)
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):
raise NotImplementedError()
pass
@abstractmethod
def row(self, rowdata):
raise NotImplementedError()
pass
class TextTableFormatter:
class TextTableFormatter(TableFormatter):
def _printer(self, data):
print(*("{: >10}".format(value) for value in data))
@ -18,7 +23,7 @@ class TextTableFormatter:
self._printer(rowdata)
class CSVTableFormatter:
class CSVTableFormatter(TableFormatter):
def _printer(self, data):
print(",".join(str(value) for value in data))
@ -29,7 +34,7 @@ class CSVTableFormatter:
return self._printer(rowdata)
class HTMLTableFormatter:
class HTMLTableFormatter(TableFormatter):
def _cell(self, value, tag):
return f"<{tag}>{value}</{tag}>"
@ -57,6 +62,9 @@ def create_formatter(name):
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])