class ErrorFilter(BaseReader, BaseWriter): temp_path = None def __init__(self, level=logging.ERROR, message="No output as errors have occurred."): from errorhandler import ErrorHandler self.handler = ErrorHandler(level) self.message = message def start(self, create=True): self.prefix = 0 self.handler.reset() if self.temp_path is not None: rmtree(self.temp_path) if create: self.temp_path = mkdtemp() else: self.temp_path = None BaseWriter.start(self) def get_stream(self, filename): self.prefix += 1 return open(os.path.join(self.temp_path, str(self.prefix) + "-" + filename), "wb") def get_workbooks(self): if self.temp_path is None: return filenames = [] for name in os.listdir(self.temp_path): d = name.split("-", 1) d.append(name) filenames.append(d) filenames.sort() for i, filename, pathname in filenames: yield ( # We currently don't open with on_demand=True here # as error filters should be lastish in the chain # so there's not much win. # However, if we did, getting rid of the temp dirs # becomes a problem as, on Windows, they can't be # deleted until the xlrd.Book object is done with # and we don't know when that might be :-( xlrd.open_workbook( os.path.join(self.temp_path, pathname), pickleable=0, formatting_info=1, on_demand=False, ragged_rows=True, ), filename, ) def sheet(self, rdsheet, wtsheet_name): self.rdsheet = rdsheet BaseWriter.sheet(self, rdsheet, wtsheet_name) def cell(self, rdrowx, rdcolx, wtrowx, wtcolx): cell = self.rdsheet.cell(rdrowx, rdcolx) if cell.ctype == xlrd.XL_CELL_EMPTY: return if cell.ctype == xlrd.XL_CELL_ERROR: logger.error( "Cell %s of sheet %r contains a bad value: %s" % ( xlrd.cellname(rdrowx, rdcolx), quoted_sheet_name(self.rdsheet.name), cell_display(cell, self.rdbook.datemode), ) ) return BaseWriter.cell(self, rdrowx, rdcolx, wtrowx, wtcolx) def finish(self): BaseWriter.finish(self) if self.handler.fired: logger.error(self.message) else: self(self.next) self.start(create=False) for attr in ("rdbook", "rdsheet"): if hasattr(self, attr): delattr(self, attr)
class ErrorFilter(BaseReader, BaseWriter): """ A filter that gates downstream writers or filters on whether or not any errors have occurred. See :ref:`error-filters` for details. """ temp_path = None def __init__(self, level=logging.ERROR, message='No output as errors have occurred.'): from errorhandler import ErrorHandler self.handler = ErrorHandler(level) self.message = message def start(self, create=True): self.prefix = 0 self.handler.reset() if self.temp_path is not None: rmtree(self.temp_path) if create: self.temp_path = mkdtemp() else: self.temp_path = None BaseWriter.start(self) def get_stream(self, filename): self.prefix += 1 return open( os.path.join(self.temp_path, str(self.prefix) + '-' + filename), 'wb') def get_workbooks(self): if self.temp_path is None: return filenames = [] for name in os.listdir(self.temp_path): d = name.split('-', 1) d.append(name) filenames.append(d) filenames.sort() for i, filename, pathname in filenames: yield ( # We currently don't open with on_demand=True here # as error filters should be lastish in the chain # so there's not much win. # However, if we did, getting rid of the temp dirs # becomes a problem as, on Windows, they can't be # deleted until the xlrd.Book object is done with # and we don't know when that might be :-( xlrd.open_workbook(os.path.join(self.temp_path, pathname), formatting_info=1, on_demand=False, ragged_rows=True), filename) def sheet(self, rdsheet, wtsheet_name): self.rdsheet = rdsheet BaseWriter.sheet(self, rdsheet, wtsheet_name) def cell(self, rdrowx, rdcolx, wtrowx, wtcolx): cell = self.rdsheet.cell(rdrowx, rdcolx) if cell.ctype == xlrd.XL_CELL_EMPTY: return if cell.ctype == xlrd.XL_CELL_ERROR: logger.error("Cell %s of sheet %r contains a bad value: %s" % ( xlrd.cellname(rdrowx, rdcolx), quoted_sheet_name(self.rdsheet.name), cell_display(cell, self.rdbook.datemode), )) return BaseWriter.cell(self, rdrowx, rdcolx, wtrowx, wtcolx) def finish(self): """ The method that triggers downstream filters and writers if no errors have occurred. """ BaseWriter.finish(self) if self.handler.fired: logger.error(self.message) else: self(self.next) self.start(create=False) for attr in ('rdbook', 'rdsheet'): if hasattr(self, attr): delattr(self, attr)