# JUBE Benchmarking Environment
# Copyright (C) 2008-2024
# Forschungszentrum Juelich GmbH, Juelich Supercomputing Centre
# http://www.fz-juelich.de/jsc/jube
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Tabletype definition"""
from __future__ import (print_function,
unicode_literals,
division)
from jube2.result_types.keyvaluesresult import KeyValuesResult
from jube2.result import Result
import xml.etree.ElementTree as ET
import jube2.log
import jube2.util.output
LOGGER = jube2.log.get_logger(__name__)
[docs]class Table(KeyValuesResult):
"""A ascii based result table"""
[docs] class TableData(KeyValuesResult.KeyValuesData):
"""Table data"""
def __init__(self, name_or_other, style, separator, transpose):
if type(name_or_other) is KeyValuesResult.KeyValuesData:
self._name = name_or_other.name
self._keys = name_or_other.keys
self._data = name_or_other.data
self._benchmark_ids = name_or_other.benchmark_ids
else:
KeyValuesResult.KeyValuesData.__init__(self, name_or_other)
self._style = style
self._separator = separator
# Ignore separator if pretty style is used
if self._style == "pretty":
self._separator = None
elif self._separator is None:
self._separator = jube2.conf.DEFAULT_SEPARATOR
self._transpose = transpose
@property
def _columns(self):
"""Get columns"""
return self._keys
@property
def style(self):
"""Get style"""
return self._style
@style.setter
def style(self, style):
"""Set style"""
self._style = style
@property
def separator(self):
"""Get separator"""
return self._separator
@separator.setter
def separator(self, separator):
"""Set separator"""
self._separator = separator
def __str__(self):
colw = list()
for column in self._columns:
if type(column) is Table.Column:
if column.colw is None:
colw.append(0)
else:
colw.append(column.colw)
else:
colw.append(0)
data = list()
data.append([column.resulting_name for column in self._columns])
data += self._data
data = [['' if c is None else c for c in r] for r in data]
if self._style == "pretty":
output = "{0}:\n".format(self.name)
else:
output = ""
output += jube2.util.output.text_table(
data, use_header_line=True, auto_linebreak=False, colw=colw,
indent=0, style=self._style,
separator=self._separator, transpose=self._transpose)
return output
[docs] def create_result(self, show=True, filename=None, **kwargs):
"""Create result output"""
# If there are multiple benchmarks, add benchmark id information
if len(set(self._benchmark_ids)) > 1:
self.add_id_information(reverse=kwargs.get("reverse", False))
result_str = str(self)
# Print result to screen
if show:
LOGGER.info(result_str)
LOGGER.info("\n")
else:
LOGGER.debug(result_str)
LOGGER.debug("\n")
# Print result to file
if filename is not None:
file_handle = open(filename, "w")
file_handle.write(result_str)
file_handle.close()
[docs] class Column(KeyValuesResult.DataKey):
"""Class represents one table column"""
def __init__(self, name, title=None, colw=None, format_string=None,
unit=None):
KeyValuesResult.DataKey.__init__(self, name, title, format_string,
unit)
self._colw = colw
@property
def colw(self):
"""Column width"""
return self._colw
[docs] def etree_repr(self):
"""Return etree object representation"""
column_etree = KeyValuesResult.DataKey.etree_repr(self)
column_etree.tag = "column"
if self._colw is not None:
column_etree.attrib["colw"] = str(self._colw)
return column_etree
def __init__(self, name, style="csv",
separator=jube2.conf.DEFAULT_SEPARATOR,
sort_names=None,
transpose=False,
res_filter=None):
KeyValuesResult.__init__(self, name, sort_names, res_filter)
self._style = style
self._separator = separator
self._transpose = transpose
[docs] def add_column(self, name, colw=None, format_string=None, title=None):
"""Add an additional column to the dataset"""
self._keys.append(Table.Column(name, title, colw, format_string))
[docs] def add_key(self, name, format_string=None, title=None, unit=None):
"""Add an additional key to the dataset"""
self._keys.append(Table.Column(name, title, None, format_string, unit))
[docs] def create_result_data(self, style, select=None, exclude=None):
"""Create result data"""
result_data = KeyValuesResult.create_result_data(self, select, exclude)
return Table.TableData(result_data,
style if style is not None else self._style,
self._separator, self._transpose)
[docs] def etree_repr(self):
"""Return etree object representation"""
result_etree = Result.etree_repr(self)
table_etree = ET.SubElement(result_etree, "table")
table_etree.attrib["name"] = self._name
table_etree.attrib["style"] = self._style
if self._separator is not None:
table_etree.attrib["separator"] = self._separator
if self._res_filter is not None:
table_etree.attrib["filter"] = self._res_filter
table_etree.attrib["transpose"] = str(self._transpose)
if len(self._sort_names) > 0:
table_etree.attrib["sort"] = \
jube2.conf.DEFAULT_SEPARATOR.join(self._sort_names)
for column in self._keys:
table_etree.append(column.etree_repr())
return result_etree