From 4c98786f0522003b4144bd38ff6861bdb57c6df3 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sat, 28 Oct 2023 19:41:40 -0500 Subject: [PATCH] ex3.7 --- reader.py | 62 ++++++++++++++++++++++++++++++++++---------------- tableformat.py | 20 +++++++++++----- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/reader.py b/reader.py index cfcb0e8..e33048a 100644 --- a/reader.py +++ b/reader.py @@ -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 diff --git a/tableformat.py b/tableformat.py index 6b72d22..af3a9b7 100644 --- a/tableformat.py +++ b/tableformat.py @@ -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}" @@ -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])