Source code for varats.table.table
"""Base table module."""
import abc
import logging
import typing as tp
from functools import reduce
from pathlib import Path
import varats.paper.case_study
from varats.table.tables import TableFormat, TableConfig
if tp.TYPE_CHECKING:
from varats.paper.case_study import CaseStudy # pylint: disable=W0611
LOG = logging.getLogger(__name__)
[docs]
class TableDataEmpty(Exception):
"""Throw if there was no input for the table."""
[docs]
class Table:
"""An abstract base class for all tables generated by VaRA-TS."""
NAME = "Table"
TABLES: tp.Dict[str, tp.Type['Table']] = {}
format_filetypes = {
TableFormat.GITHUB: "md",
TableFormat.HTML: "html",
TableFormat.UNSAFEHTML: "html",
TableFormat.LATEX: "tex",
TableFormat.LATEX_RAW: "tex",
TableFormat.LATEX_BOOKTABS: "tex",
TableFormat.RST: "rst",
}
def __init__(self, table_config: TableConfig, **kwargs: tp.Any) -> None:
self.__table_config = table_config
self.__saved_extra_args = kwargs
@classmethod
def __init_subclass__(
cls, *, table_name: tp.Optional[str], **kwargs: tp.Any
) -> None:
"""Register concrete tables."""
super().__init_subclass__(**kwargs)
if table_name:
cls.NAME = table_name
cls.TABLES[table_name] = cls
[docs]
@staticmethod
def get_table_types_help_string() -> str:
"""
Generates help string for visualizing all available tables.
Returns:
a help string that contains all available table names.
"""
return "The following tables are available:\n " + "\n ".join(
list(Table.TABLES)
)
[docs]
@staticmethod
def get_class_for_table_type(table_type: str) -> tp.Type['Table']:
"""
Get the class for table from the table registry.
Args:
table_type: The name of the table.
Returns: The class implementing the table.
"""
if table_type not in Table.TABLES:
raise LookupError(
f"Unknown table '{table_type}'.\n" +
Table.get_table_types_help_string()
)
table_cls = Table.TABLES[table_type]
return table_cls
@property
def name(self) -> str:
"""
Name of the current table.
Test:
>>> Table(TableConfig.from_kwargs(view=False)).name
'Table'
"""
return self.NAME
@property
def table_config(self) -> TableConfig:
"""Table config for this table."""
return self.__table_config
@property
def table_kwargs(self) -> tp.Any:
"""
Access the kwargs passed to the initial table.
Test:
>>> p = Table(TableConfig.from_kwargs(view=False), foo='bar',\
baz='bazzer')
>>> p.table_kwargs['foo']
'bar'
>>> p.table_kwargs['baz']
'bazzer'
"""
return self.__saved_extra_args
[docs]
@staticmethod
def supports_stage_separation() -> bool:
"""True, if the table supports stage separation, i.e., the table can be
drawn separating the different stages in a case study."""
return False
[docs]
@abc.abstractmethod
def tabulate(self, table_format: TableFormat, wrap_table: bool) -> str:
"""
Build the table using tabulate.
Args:
table_format: the format to use for the table
wrap_table: whether to wrap the table in a separate
document (latex only)
"""
[docs]
def table_file_name(self, table_format: TableFormat) -> str:
"""
Get the file name this table; will be stored to when calling save.
Automatically deduces this tables' filetype from its format.
Returns:
the file name the table will be stored to
Test:
>>> p = Table(TableConfig.from_kwargs(view=False), project='bar')
>>> p.table_file_name(TableFormat.PLAIN)
'bar_Table.txt'
>>> from varats.paper.case_study import CaseStudy
>>> p = Table(TableConfig.from_kwargs(view=False),\
project='bar', case_study=CaseStudy('baz', 42))
>>> p.table_file_name(TableFormat.LATEX_BOOKTABS)
'baz_42_Table.tex'
"""
table_ident = ''
if 'case_study' in self.table_kwargs:
case_study = self.table_kwargs['case_study']
if isinstance(case_study, varats.paper.case_study.CaseStudy):
table_ident = f"{case_study.project_name}_{case_study.version}_"
else:
table_ident = reduce(
lambda x, y: f'{x}{y.project_name}_', case_study, ''
)
elif 'project' in self.table_kwargs:
table_ident = f"{self.table_kwargs['project']}_"
sep_stages = ''
if self.supports_stage_separation(
) and self.table_kwargs.get('sep_stages', None):
sep_stages = 'S'
filetype = self.format_filetypes.get(table_format, "txt")
return f"{table_ident}{self.name}{sep_stages}.{filetype}"
[docs]
def show(self) -> None:
"""Show the current table in console."""
try:
table = self.tabulate(TableFormat.FANCY_GRID, False)
except TableDataEmpty:
LOG.warning("No data for the current project.")
return
print(table)
[docs]
def save(
self, path: Path, table_format: TableFormat, wrap_table: bool
) -> None:
"""
Save the current table to a file.
Args:
path: the path where the file is stored (excluding file name)
table_format: the format to use for the table
wrap_table: whether to wrap the table in a separate
document (latex only)
"""
try:
table = self.tabulate(table_format, wrap_table)
except TableDataEmpty:
LOG.warning("No data for this table.")
return
with open(path / self.table_file_name(table_format), "w") as outfile:
outfile.write(table)