Skip to content

Commit

Permalink
refactor: reusable protocols for tabular data
Browse files Browse the repository at this point in the history
Create reusable protocols for data that is table-like.

HasColumn requires get_title instead of specific attributes, i.e. the
title of a column is decided by the column instead of the formatter in
this case.
  • Loading branch information
jsolaas committed Jul 3, 2024
1 parent 8b57915 commit eda51f0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 40 deletions.
23 changes: 20 additions & 3 deletions src/libecalc/domain/tabular/tabular.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import abc
from typing import List, Protocol, TypeVar, Union
from typing import List, Protocol, TypeVar

ColumnIndex = TypeVar("ColumnIndex")
RowIndex = TypeVar("RowIndex")

TValue = TypeVar("TValue", covariant=True)

class Tabular(Protocol[RowIndex, ColumnIndex]):

class Tabular(Protocol[RowIndex, ColumnIndex, TValue]):
@property
@abc.abstractmethod
def row_ids(self) -> List[RowIndex]:
Expand All @@ -17,5 +19,20 @@ def column_ids(self) -> List[ColumnIndex]:
...

@abc.abstractmethod
def get_value(self, row_id: RowIndex, column_id: ColumnIndex) -> Union[int, float]:
def get_value(self, row_id: RowIndex, column_id: ColumnIndex) -> TValue:
...


class Column(Protocol):
@abc.abstractmethod
def get_title(self) -> str:
...


TColumn = TypeVar("TColumn", bound=Column, covariant=True)


class HasColumns(Protocol[TColumn]):
@abc.abstractmethod
def get_column(self, column_id: ColumnIndex) -> TColumn:
...
6 changes: 6 additions & 0 deletions src/libecalc/presentation/exporter/dto/dtos.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class DataSeries:
title: str
values: List[Union[str, float]]

def get_title(self) -> str:
return self.title

@property
def id(self) -> str:
return self.name
Expand All @@ -36,6 +39,9 @@ class QueryResult:
unit: Unit # Needed! in order to know how to handler further....parse
values: Dict[datetime, float]

def get_title(self) -> str:
return f"{self.title}[{self.unit}]"

@property
def id(self) -> str:
return self.name
Expand Down
40 changes: 5 additions & 35 deletions src/libecalc/presentation/exporter/formatters/formatter.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,15 @@
import abc
from datetime import datetime
from typing import Dict, Iterator, List, Optional, Protocol, Tuple, Union
from typing import Dict, Iterator, List, Protocol, Tuple, Union

from libecalc.common.units import Unit
from libecalc.domain.tabular.tabular import Tabular
from libecalc.domain.tabular.tabular import HasColumns, Tabular

RowIndex = Union[str, int, float, datetime]
ColumnIndex = Union[str]


class ColumnWithoutUnit(Protocol):
@property
@abc.abstractmethod
def title(self) -> str:
...


class ColumnWithUnit(ColumnWithoutUnit, Protocol):
@property
@abc.abstractmethod
def unit(self) -> Optional[Unit]:
...


Column = Union[ColumnWithUnit, ColumnWithoutUnit]


class Formattable(Tabular[RowIndex, ColumnIndex], Protocol):
@abc.abstractmethod
def get_column(self, column_id: ColumnIndex) -> Column:
...
class Formattable(Tabular, HasColumns, Protocol):
...


class FormattableGroup(Protocol):
Expand Down Expand Up @@ -57,22 +37,12 @@ class CSVFormatter:
def __init__(self, separation_character: str = ","):
self.separation_character = separation_character

@staticmethod
def _format_column_info(column: Column) -> str:
info_str = f"{column.title}"

if hasattr(column, "unit"):
info_str += f"[{column.unit}]"
return info_str

def format(self, tabular: Formattable) -> List[str]:
column_ids = tabular.column_ids
rows: List[str] = [
self.separation_character.join(list(column_ids)),
"#"
+ self.separation_character.join(
[self._format_column_info(tabular.get_column(column_id)) for column_id in column_ids]
),
+ self.separation_character.join([tabular.get_column(column_id).get_title() for column_id in column_ids]),
]

for row_id in tabular.row_ids:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
class Column:
id: str
title: str
unit: Unit
unit: Unit = Unit.TONS

def get_title(self) -> str:
return f"{self.title}[{self.unit}]"


@dataclass
Expand All @@ -26,7 +29,6 @@ def get_column(self, column_id: ColumnIndex) -> Column:
return Column(
id=column_id,
title=column_id.upper(),
unit=Unit.TONS,
)

@property
Expand Down

0 comments on commit eda51f0

Please sign in to comment.