From a105834934164c82570e6f8d4e36116958e16d9e Mon Sep 17 00:00:00 2001 From: Kostis Anagnostopoulos Date: Wed, 14 Jun 2017 02:51:49 +0200 Subject: [PATCH] refact(table): encapsulate buf.getCell() & improve logging + Centralize error-reporting for cell indexing-errors. + Logging: + Restore start offset-logging on cell indexing errors. + Class-logger-->module-var, not to waste loggers with each new object. + Stop specifying log-levels (must be done to all loggers). --- vitables/plugins/timeseries/time_series.py | 14 +++++---- vitables/vttables/buffer.py | 36 ++++++---------------- vitables/vttables/datasheet.py | 12 +++----- vitables/vttables/leaf_model.py | 18 ++++++++--- 4 files changed, 35 insertions(+), 45 deletions(-) diff --git a/vitables/plugins/timeseries/time_series.py b/vitables/plugins/timeseries/time_series.py index 6975e0e1..77fda106 100644 --- a/vitables/plugins/timeseries/time_series.py +++ b/vitables/plugins/timeseries/time_series.py @@ -231,7 +231,7 @@ def customiseModel(self, datasheet): leaf_kind = 'array' model_info = { 'leaf_kind': leaf_kind, - 'rbuffer': model.rbuffer, + 'model': model, 'numrows': model.rowCount(), 'formatContent': model.formatContent, } @@ -298,7 +298,7 @@ def __init__(self, model_info, ts_info, parent=None): self.ts_freq = ts_info['ts_freq'] self.ts_format = ts_info['ts_format'] # Attributes required by the data() method - self.rbuffer = model_info['rbuffer'] + self.model = model_info['model'] self.numrows = model_info['numrows'] self.ts_cols = ts_info['ts_cols'] self.formatContent = model_info['formatContent'] @@ -322,12 +322,13 @@ def table_data(self, index, role=QtCore.Qt.DisplayRole): - `index`: the index of a data item - `role`: the role being returned """ + row, col = index.row(), index.column() - if not index.isValid() or not (0 <= index.row() < self.nrows): + if not index.isValid() or not (0 <= row < self.nrows): return None if role == QtCore.Qt.DisplayRole: - cell = self.rbuffer.getCell(index.row(), index.column()) + cell = self.model.cell(row, col) if index.column() in self.ts_cols: return self.tsFormatter(cell) return self.formatContent(cell) @@ -348,12 +349,13 @@ def array_data(self, index, role=QtCore.Qt.DisplayRole): - `index`: the index of a data item - `role`: the role being returned """ + row, col = index.row(), index.column() - if not index.isValid() or not (0 <= index.row() < self.nrows): + if not index.isValid() or not (0 <= row < self.nrows): return None if role == QtCore.Qt.DisplayRole: - cell = self.rbuffer.getCell(index.row(), index.column()) + cell = self.model.cell(row, col) return self.tsFormatter(cell) if role == QtCore.Qt.TextAlignmentRole: diff --git a/vitables/vttables/buffer.py b/vitables/vttables/buffer.py index e9ae953c..5571ee44 100644 --- a/vitables/vttables/buffer.py +++ b/vitables/vttables/buffer.py @@ -48,6 +48,8 @@ warnings.filterwarnings('ignore', category=tables.FlavorWarning) warnings.filterwarnings('ignore', category=tables.NaturalNameWarning) +log = logging.getLogger(__name__) + class Buffer(object): """Buffer used to access the real data contained in `PyTables` datasets. @@ -81,9 +83,6 @@ def __init__(self, leaf): Initializes the buffer. """ - self.logger = logging.getLogger(__name__) - self.logger.setLevel(logging.INFO) - self.leaf = leaf # The numpy array where read data will be stored @@ -161,7 +160,7 @@ def isDataSourceReadable(self): except tables.HDF5ExtError: readable = False # TODO: Fix error msg to include exception or merge with below. - self.logger.error( + log.error( translate('Buffer', """Problems reading records. The dataset """ """seems to be compressed with the {0} library. """ @@ -171,7 +170,7 @@ def isDataSourceReadable(self): self.leaf.filters.complib)) except ValueError as e: readable = False - self.logger.error( + log.error( translate('Buffer', 'Data read error: {}', 'A dataset read error').format(e.message)) return readable @@ -204,7 +203,7 @@ def readBuffer(self, start, stop): data = self.leaf.read(start, stop) except tables.HDF5ExtError: # TODO: Fix error msg to include exception. - self.logger.error( + log.error( translate('Buffer', """\nError: problems reading records. """ """The dataset maybe corrupted.""", 'A dataset readability error')) @@ -228,12 +227,7 @@ def scalarCell(self, row, col): :Returns: the cell at position `(row, col)` of the document """ - - try: - return self.chunk[()] - except IndexError: - self.logger.error('IndexError! row, column: {1}, {2}' - .format(row, col)) + return self.chunk[()] def vectorCell(self, row, col): """ @@ -260,11 +254,7 @@ def vectorCell(self, row, col): # get the right chunk element. # chunk = [row0, row1, row2, ..., rowN] # and columns can be read from a given row using indexing notation - try: - return self.chunk[row] - except IndexError: - self.logger.error('IndexError! row, column: {1}, {2}' - .format(row, col)) + return self.chunk[row] def EArrayCell(self, row, col): """ @@ -287,11 +277,7 @@ def EArrayCell(self, row, col): # and columns can be read from a given row using indexing notation # TODO: this method should be improved as it requires to read the # whola array keeping the read data in memory - try: - return self.leaf.read()[row] - except IndexError: - self.logger.error('IndexError! row, column: {1}, {2}' - .format(row, col)) + return self.leaf.read()[row] def arrayCell(self, row, col): """ @@ -316,8 +302,4 @@ def arrayCell(self, row, col): # For tables we have # chunk = [nestedrecord0, nestedrecord1, ..., nestedrecordN] # and fields can be read from nestedrecordJ using indexing notation - try: - return self.chunk[row][col] - except IndexError: - self.logger.error('IndexError! row, column: {1}, {2}' - .format(row, col)) + return self.chunk[row][col] diff --git a/vitables/vttables/datasheet.py b/vitables/vttables/datasheet.py index eb94e40c..5720d41b 100644 --- a/vitables/vttables/datasheet.py +++ b/vitables/vttables/datasheet.py @@ -94,7 +94,6 @@ def __init__(self, index): self.aboutToActivate.connect(self.syncTreeView) self.leaf_view.doubleClicked.connect(self.zoomCell) - def closeEvent(self, event): """Close the window cleanly with the close button of the title bar. @@ -112,7 +111,6 @@ def closeEvent(self, event): if self.vtgui.workspace.subWindowList() == []: self.vtgui.dbs_tree_view.setFocus(True) - def focusInEvent(self, event): """Specialised handler for focus events. @@ -128,7 +126,6 @@ def focusInEvent(self, event): self.syncTreeView() self.setFocus(True) - def syncTreeView(self): """ If the view is activated select its leaf in the tree of databases view. @@ -143,7 +140,6 @@ def syncTreeView(self): self.vtgui.dbs_tree_view.setCurrentIndex( QtCore.QModelIndex(self.pindex)) - def zoomCell(self, index): """Display the inner dimensions of a cell. @@ -153,7 +149,7 @@ def zoomCell(self, index): row = index.row() column = index.column() tmodel = index.model() - data = tmodel.rbuffer.getCell(row, column) + data = tmodel.cell(row, column) # The title of the zoomed view node = self.dbt_leaf @@ -161,10 +157,10 @@ def zoomCell(self, index): if node.node_kind == 'table': col = info.columns_names[column] title = '{0}: {1}[{2}]'.format(node.name, col, - tmodel.start + row) + tmodel.start + row) else: title = '{0}: ({1},{2})'.format(node.name, - tmodel.start + row, column) + tmodel.start + row, column) zoom_cell.ZoomCell(data, title, self.vtgui.workspace, - self.dbt_leaf) + self.dbt_leaf) diff --git a/vitables/vttables/leaf_model.py b/vitables/vttables/leaf_model.py index 5de12df0..8f1e8bd8 100644 --- a/vitables/vttables/leaf_model.py +++ b/vitables/vttables/leaf_model.py @@ -26,17 +26,19 @@ __docformat__ = 'restructuredtext' +import logging import vitables.utils +from vitables.vttables import buffer from qtpy import QtCore import tables -from vitables.vttables import buffer - #: The maximum number of rows to be read from the data source. CHUNK_SIZE = 10000 +log = logging.getLogger(__name__) + class LeafModel(QtCore.QAbstractTableModel): """ @@ -207,15 +209,23 @@ def data(self, index, role=QtCore.Qt.DisplayRole): - `index`: the index of a data item - `role`: the role being returned """ + row, col = index.row(), index.column() - if not index.isValid() or not (0 <= index.row() < self.numrows): + if not index.isValid() or not (0 <= row < self.numrows): return None if role == QtCore.Qt.DisplayRole: - cell = self.rbuffer.getCell(index.row(), index.column()) + cell = self.cell(row, col) return self.formatContent(cell) if role == QtCore.Qt.TextAlignmentRole: return QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop return None + + def cell(self, row, col): + try: + return self.rbuffer.getCell(row, col) + except IndexError: + log.error('IndexError! buffer start: {0} row, column: ' + '{1}, {2}'.format(self.start, row, col))