Fitting file import improvements:

- Blank files don't cause crash
- If error happens during processing, notify user
This commit is contained in:
blitzmann
2016-01-03 21:45:19 -05:00
parent ef1228eb32
commit 343d605a84
2 changed files with 59 additions and 24 deletions

View File

@@ -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:

View File

@@ -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)