From 88f54d1a2f2b3c886dc6a6ffb647df6f9e334e22 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 4 Feb 2024 10:28:09 -0600 Subject: [PATCH] ex 9 --- simplemod.py | 13 +++++ stock.py | 5 +- structly/__init__.py | 9 +++ reader.py => structly/reader.py | 5 +- structure.py => structly/structure.py | 4 +- structly/tableformat/__init__.py | 3 + structly/tableformat/csv.py | 12 ++++ .../tableformat/formatter.py | 58 +++++-------------- structly/tableformat/html.py | 16 +++++ structly/tableformat/text.py | 13 +++++ validate.py => structly/validate.py | 0 11 files changed, 89 insertions(+), 49 deletions(-) create mode 100644 simplemod.py create mode 100644 structly/__init__.py rename reader.py => structly/reader.py (91%) rename structure.py => structly/structure.py (96%) create mode 100644 structly/tableformat/__init__.py create mode 100644 structly/tableformat/csv.py rename tableformat.py => structly/tableformat/formatter.py (51%) create mode 100644 structly/tableformat/html.py create mode 100644 structly/tableformat/text.py rename validate.py => structly/validate.py (100%) diff --git a/simplemod.py b/simplemod.py new file mode 100644 index 0000000..ff156ab --- /dev/null +++ b/simplemod.py @@ -0,0 +1,13 @@ +x = 42 + + +def foo(): + print('x is', x) + + +class Spam: + def yow(self): + print('Yow!') + + +print('loaded simplemod') diff --git a/stock.py b/stock.py index d829351..809f3f9 100644 --- a/stock.py +++ b/stock.py @@ -1,4 +1,4 @@ -from structure import Structure +from structly import * class Stock(Structure): @@ -21,6 +21,7 @@ class Stock(Structure): if __name__ == '__main__': - from reader import read_csv_as_instances portfolio = read_csv_as_instances('Data/portfolio.csv', Stock) + formatter = create_formatter('text') + print_table(portfolio, ['name', 'shares', 'price'], formatter) diff --git a/structly/__init__.py b/structly/__init__.py new file mode 100644 index 0000000..2aca69a --- /dev/null +++ b/structly/__init__.py @@ -0,0 +1,9 @@ +from .reader import * +from .structure import * +from .tableformat import * + +__all__ = [ + *structure.__all__, + *reader.__all__, + *tableformat.__all__ +] diff --git a/reader.py b/structly/reader.py similarity index 91% rename from reader.py rename to structly/reader.py index 9b7c465..40906fc 100644 --- a/reader.py +++ b/structly/reader.py @@ -2,6 +2,8 @@ import csv import logging from typing import Any, Callable, Iterable, Mapping, Optional, Sequence +__all__ = ['read_csv_as_dicts', 'read_csv_as_instances'] + def convert_csv( lines: Iterable[str], @@ -24,7 +26,8 @@ def convert_csv( def csv_as_dicts( - lines: Iterable[str], types: Sequence[type], headers: Optional[Sequence[str]] = None + lines: Iterable[str], types: Sequence[type], + headers: Optional[Sequence[str]] = None ) -> Sequence[Mapping[str, Any]]: """Parse CSV lines into a list of dictionaries.""" diff --git a/structure.py b/structly/structure.py similarity index 96% rename from structure.py rename to structly/structure.py index c0407d0..9002a18 100644 --- a/structure.py +++ b/structly/structure.py @@ -1,6 +1,8 @@ from collections import ChainMap -from validate import Validator, validated +from .validate import Validator, validated + +__all__ = ['Structure'] def validate_attributes(cls): diff --git a/structly/tableformat/__init__.py b/structly/tableformat/__init__.py new file mode 100644 index 0000000..b7ecfdd --- /dev/null +++ b/structly/tableformat/__init__.py @@ -0,0 +1,3 @@ +from .formatter import create_formatter, print_table + +__all__ = ['create_formatter', 'print_table'] diff --git a/structly/tableformat/csv.py b/structly/tableformat/csv.py new file mode 100644 index 0000000..3d2225f --- /dev/null +++ b/structly/tableformat/csv.py @@ -0,0 +1,12 @@ +from .formatter import TableFormatter + + +class CSVTableFormatter(TableFormatter): + def _printer(self, data): + print(",".join(str(value) for value in data)) + + def headings(self, headers): + return self._printer(headers) + + def row(self, rowdata): + return self._printer(rowdata) diff --git a/tableformat.py b/structly/tableformat/formatter.py similarity index 51% rename from tableformat.py rename to structly/tableformat/formatter.py index c47f153..879f77b 100644 --- a/tableformat.py +++ b/structly/tableformat/formatter.py @@ -2,6 +2,13 @@ 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 @@ -11,44 +18,6 @@ class TableFormatter(ABC): pass -class TextTableFormatter(TableFormatter): - def _printer(self, data): - print(*("{: >10}".format(value) for value in data)) - - def headings(self, headers): - self._printer(headers) - print(*("{:->10}".format("") for _ in headers)) - - def row(self, rowdata): - self._printer(rowdata) - - -class CSVTableFormatter(TableFormatter): - def _printer(self, data): - print(",".join(str(value) for value in data)) - - def headings(self, headers): - return self._printer(headers) - - def row(self, rowdata): - return self._printer(rowdata) - - -class HTMLTableFormatter(TableFormatter): - def _cell(self, value, tag): - return f"<{tag}>{value}" - - def _printer(self, data, tag): - line = f"{' '.join(self._cell(str(value), tag) for value in data)}" - print(line) - - def headings(self, headers): - return self._printer(headers, "th") - - def row(self, rowdata): - return self._printer(rowdata, "td") - - class ColumnFormatMixin: formats = [] @@ -63,16 +32,15 @@ class UpperHeadersMixin: def create_formatter(name, column_formats=None, upper_headers=False): - formatters = { - "text": TextTableFormatter, - "csv": CSVTableFormatter, - "html": HTMLTableFormatter, - } - formatter = formatters.get(name, None) if not name: raise ValueError(f'formatter named "{name}" not implemented') - if upper_headers: + 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 diff --git a/structly/tableformat/html.py b/structly/tableformat/html.py new file mode 100644 index 0000000..1de222f --- /dev/null +++ b/structly/tableformat/html.py @@ -0,0 +1,16 @@ +from .formatter import TableFormatter + + +class HTMLTableFormatter(TableFormatter): + def _cell(self, value, tag): + return f"<{tag}>{value}" + + def _printer(self, data, tag): + line = f"{' '.join(self._cell(str(value), tag) for value in data)}" + print(line) + + def headings(self, headers): + return self._printer(headers, "th") + + def row(self, rowdata): + return self._printer(rowdata, "td") diff --git a/structly/tableformat/text.py b/structly/tableformat/text.py new file mode 100644 index 0000000..28f3076 --- /dev/null +++ b/structly/tableformat/text.py @@ -0,0 +1,13 @@ +from .formatter import TableFormatter + + +class TextTableFormatter(TableFormatter): + def _printer(self, data): + print(*("{: >10}".format(value) for value in data)) + + def headings(self, headers): + self._printer(headers) + print(*("{:->10}".format("") for _ in headers)) + + def row(self, rowdata): + self._printer(rowdata) diff --git a/validate.py b/structly/validate.py similarity index 100% rename from validate.py rename to structly/validate.py