diff --git a/gui/mainFrame.py b/gui/mainFrame.py index f191c8f19..3c47e08fd 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -786,7 +786,7 @@ class MainFrame(wx.Frame): else: self.progressDialog.Update(info) - def fileImportCallback(self, info, fits=None): + def fileImportCallback(self, action, data=None): """ While importing fits from file, the logic calls back to this function to update progress bar to show activity. XML files can contain multiple @@ -794,18 +794,28 @@ class MainFrame(wx.Frame): a single ship. When iterating through the files, we update the message when we start a new file, and then Pulse the progress bar with every fit that is processed. + + action : a flag that lets us know how to deal with :data + None: Pulse the progress bar + 1: Replace message with data + other: Close dialog and handle based on :action (-1 open fits, -2 display error) """ - if info == -1: - self.closeProgressDialog() - self._openAfterImport(fits) - elif info != self.progressDialog.message and info is not None: - # New message, overwrite cached message and update - self.progressDialog.message = info - self.progressDialog.Pulse(info) - else: - # Simply Pulse() if we don't have anything else to do + if action is None: self.progressDialog.Pulse() + elif action == 1 and data != self.progressDialog.message: + self.progressDialog.message = data + self.progressDialog.Pulse(data) + else: + self.closeProgressDialog() + if action == -1: + self._openAfterImport(data) + elif action == -2: + dlg = wx.MessageDialog(self, + "The following error was generated\n\n%s\n\nBe aware that already processed fits were not saved"%data, + "Import Error", wx.OK | wx.ICON_ERROR) + if dlg.ShowModal() == wx.ID_OK: + return def _openAfterImport(self, fits): if len(fits) > 0: diff --git a/service/fit.py b/service/fit.py index 1bd027486..b50ec1ae7 100644 --- a/service/fit.py +++ b/service/fit.py @@ -24,6 +24,8 @@ import logging import wx from codecs import open +import xml.parsers.expat + import eos.db import eos.types @@ -65,10 +67,13 @@ class FitImportThread(threading.Thread): def run(self): sFit = Fit.getInstance() - fits = sFit.importFitFromFiles(self.paths, self.callback) + success, result = sFit.importFitFromFiles(self.paths, self.callback) - # Send done signal to GUI - wx.CallAfter(self.callback, -1, fits) + if not success: # there was an error during processing + logger.error("Error while processing file import: %s", result) + wx.CallAfter(self.callback, -2, result) + else: # Send done signal to GUI + wx.CallAfter(self.callback, -1, result) class Fit(object): @@ -849,37 +854,48 @@ class Fit(object): fits = [] for path in paths: if callback: # Pulse - wx.CallAfter(callback, "Processing file:\n%s"%path) + wx.CallAfter(callback, 1, "Processing file:\n%s"%path) file = open(path, "r") srcString = file.read() + + if len(srcString) == 0: # ignore blank files + continue + codec_found = None # If file had ANSI encoding, decode it to unicode using detection # of BOM header or if there is no header try default # codepage then fallback to utf-16, cp1252 if isinstance(srcString, str): - encoding_map = (('\xef\xbb\xbf', 'utf-8'),('\xff\xfe\0\0', 'utf-32'),('\0\0\xfe\xff', 'UTF-32BE'),('\xff\xfe', 'utf-16'),('\xfe\xff', 'UTF-16BE')) + encoding_map = ( + ('\xef\xbb\xbf', 'utf-8'), + ('\xff\xfe\0\0', 'utf-32'), + ('\0\0\xfe\xff', 'UTF-32BE'), + ('\xff\xfe', 'utf-16'), + ('\xfe\xff', 'UTF-16BE')) + for bom, encoding in encoding_map: if srcString.startswith(bom): codec_found = encoding savebom = bom if codec_found is None: - logger.warn("Unicode BOM not found in file %s.", path) + logger.info("Unicode BOM not found in file %s.", path) attempt_codecs = (defcodepage, "utf-8", "utf-16", "cp1252") + for page in attempt_codecs: try: - logger.warn("Attempting to decode file %s using %s page.", path, page) + logger.info("Attempting to decode file %s using %s page.", path, page) srcString = unicode(srcString, page) codec_found = page - logger.warn("File %s decoded using %s page.", path, page) + logger.info("File %s decoded using %s page.", path, page) except UnicodeDecodeError: - logger.warn("Error unicode decoding %s from page %s, trying next codec", path, page) + logger.info("Error unicode decoding %s from page %s, trying next codec", path, page) else: break else: - logger.debug("Unicode BOM detected in %s, using %s page.", path, codec_found) + logger.info("Unicode BOM detected in %s, using %s page.", path, codec_found) srcString = unicode(srcString[len(savebom):], codec_found) else: @@ -889,8 +905,17 @@ class Fit(object): else: codec_found = "utf-8" - _, fitsImport = Port.importAuto(srcString, path, callback=callback, encoding=codec_found) - fits += fitsImport + if codec_found is None: + return False, "Proper codec could not be established for %s" % path + + try: + _, fitsImport = Port.importAuto(srcString, path, callback=callback, encoding=codec_found) + fits += fitsImport + except xml.parsers.expat.ExpatError, e: + return False, "Malformed XML in %s"%path + except Exception, e: + logger.exception("Unknown exception processing: %s", path) + return False, "Unknown Error while processing %s"%path IDs = [] numFits = len(fits) @@ -903,12 +928,12 @@ class Fit(object): IDs.append(fit.ID) if callback: # Pulse wx.CallAfter( - callback, + callback, 1, "Processing complete, saving fits to database\n(%d/%d)" % (i+1, numFits) ) - return fits + return True, fits def importFitFromBuffer(self, bufferStr, activeFit=None): _, fits = Port.importAuto(bufferStr, activeFit=activeFit)