diff --git a/pyfa.py b/pyfa.py index 488165724..35ea27764 100755 --- a/pyfa.py +++ b/pyfa.py @@ -23,11 +23,32 @@ import os import os.path import re import config +import traceback from optparse import OptionParser, BadOptionError, AmbiguousOptionError +# Import everything +# noinspection PyPackageRequirements +import os +import os.path + from logbook import TimedRotatingFileHandler, Logger, StreamHandler, NestedSetup, FingersCrossedHandler, NullHandler, \ CRITICAL, ERROR, WARNING, DEBUG, INFO + +try: + import wxversion + import wx + from gui.errorDialog import ErrorFrame +except ImportError: + wxversion = None + wx = None + ErrorFrame = None + +try: + import sqlalchemy +except ImportError: + sqlalchemy = None + pyfalog = Logger(__name__) @@ -37,6 +58,7 @@ class PassThroughOptionParser(OptionParser): OSX passes -psn_0_* argument, which is something that pyfa does not handle. See GH issue #423 """ + def _process_args(self, largs, rargs, values): while rargs: try: @@ -91,78 +113,18 @@ elif options.logginglevel == "Debug": else: options.logginglevel = ERROR -if not hasattr(sys, 'frozen'): - - if sys.version_info < (2, 6) or sys.version_info > (3, 0): - print("Pyfa requires python 2.x branch ( >= 2.6 )\nExiting.") - sys.exit(1) - - try: - import wxversion - except ImportError: - wxversion = None - print("Cannot find wxPython\nYou can download wxPython (2.8+) from http://www.wxpython.org/") - sys.exit(1) - - try: - if options.force28 is True: - wxversion.select('2.8') - else: - wxversion.select(['3.0', '2.8']) - except wxversion.VersionError: - print("Installed wxPython version doesn't meet requirements.\nYou can download wxPython 2.8 or 3.0 from http://www.wxpython.org/") - sys.exit(1) - - try: - import sqlalchemy - - saVersion = sqlalchemy.__version__ - saMatch = re.match("([0-9]+).([0-9]+)([b\.])([0-9]+)", saVersion) - if saMatch: - saMajor = int(saMatch.group(1)) - saMinor = int(saMatch.group(2)) - betaFlag = True if saMatch.group(3) == "b" else False - saBuild = int(saMatch.group(4)) if not betaFlag else 0 - if saMajor == 0 and (saMinor < 5 or (saMinor == 5 and saBuild < 8)): - print("Pyfa requires sqlalchemy 0.5.8 at least but current sqlalchemy version is %s\n" - "You can download sqlalchemy (0.5.8+) from http://www.sqlalchemy.org/".format(sqlalchemy.__version__)) - sys.exit(1) - else: - print("Unknown sqlalchemy version string format, skipping check") - - except ImportError: - sqlalchemy = None - print("Cannot find sqlalchemy.\nYou can download sqlalchemy (0.6+) from http://www.sqlalchemy.org/") - sys.exit(1) - - # check also for dateutil module installed. - try: - # noinspection PyPackageRequirements - import dateutil.parser # noqa - Copied import statement from service/update.py - except ImportError: - dateutil = None - print("Cannot find python-dateutil.\nYou can download python-dateutil from https://pypi.python.org/pypi/python-dateutil") - sys.exit(1) - - if __name__ == "__main__": - # Configure paths - if options.rootsavedata is True: - config.saveInRoot = True - - # set title if it wasn't supplied by argument - if options.title is None: - options.title = "pyfa %s%s - Python Fitting Assistant" % (config.version, "" if config.tag.lower() != 'git' else " (git)") - - config.debug = options.debug - - # Import everything - # noinspection PyPackageRequirements - import wx - import os - import os.path - try: + # Configure paths + if options.rootsavedata is True: + config.saveInRoot = True + + # set title if it wasn't supplied by argument + if options.title is None: + options.title = "pyfa %s%s - Python Fitting Assistant" % (config.version, "" if config.tag.lower() != 'git' else " (git)") + + config.debug = options.debug + # convert to unicode if it is set if options.savepath is not None: options.savepath = unicode(options.savepath) @@ -195,16 +157,16 @@ if __name__ == "__main__": # if we run out of setup handling NullHandler(), StreamHandler( - sys.stdout, - bubble=False, - level=options.logginglevel + sys.stdout, + bubble=False, + level=options.logginglevel ), TimedRotatingFileHandler( - savePath_Destination, - level=0, - backup_count=3, - bubble=True, - date_format='%Y-%m-%d', + savePath_Destination, + level=0, + backup_count=3, + bubble=True, + date_format='%Y-%m-%d', ), ]) else: @@ -214,76 +176,128 @@ if __name__ == "__main__": # if we run out of setup handling NullHandler(), FingersCrossedHandler( - TimedRotatingFileHandler( - savePath_Destination, - level=0, - backup_count=3, - bubble=False, - date_format='%Y-%m-%d', - ), - action_level=ERROR, - buffer_size=1000, - # pull_information=True, - # reset=False, + TimedRotatingFileHandler( + savePath_Destination, + level=0, + backup_count=3, + bubble=False, + date_format='%Y-%m-%d', + ), + action_level=ERROR, + buffer_size=1000, + # pull_information=True, + # reset=False, ) ]) except: + print("Critical error attempting to setup logging. Falling back to console only.") logging_mode = "Console Only" logging_setup = NestedSetup([ # make sure we never bubble up to the stderr handler # if we run out of setup handling NullHandler(), StreamHandler( - sys.stdout, - bubble=False + sys.stdout, + bubble=False ) ]) - import eos.db - # noinspection PyUnresolvedReferences - import service.prefetch # noqa: F401 - - # Make sure the saveddata db exists - if not os.path.exists(config.savePath): - os.mkdir(config.savePath) - - eos.db.saveddata_meta.create_all() - except Exception, e: - import traceback - from gui.errorDialog import ErrorFrame - tb = traceback.format_exc() pyfa = wx.App(False) ErrorFrame(e, tb) pyfa.MainLoop() + raise sys.exit() with logging_setup.threadbound(): - # Don't redirect if frozen - if not hasattr(sys, 'frozen'): - # Output all stdout (print) messages as warnings - try: - sys.stdout = LoggerWriter(pyfalog.warning) - except ValueError, Exception: - pyfalog.critical("Cannot access log file. Continuing without writing stdout to log.") + try: + pyfalog.info("Starting Pyfa") - if not options.debug: - # Output all stderr (stacktrace) messages as critical + # Don't redirect if frozen + if not hasattr(sys, 'frozen'): + # Output all stdout (print) messages as warnings try: - sys.stderr = LoggerWriter(pyfalog.critical) + sys.stdout = LoggerWriter(pyfalog.warning) except ValueError, Exception: - pyfalog.critical("Cannot access log file. Continuing without writing stderr to log.") + pyfalog.critical("Cannot access log file. Continuing without writing stdout to log.") - pyfalog.info("Starting Pyfa") - pyfalog.info("Running in logging mode: {0}", logging_mode) + if not options.debug: + # Output all stderr (stacktrace) messages as critical + try: + sys.stderr = LoggerWriter(pyfalog.critical) + except ValueError, Exception: + pyfalog.critical("Cannot access log file. Continuing without writing stderr to log.") - if hasattr(sys, 'frozen') and options.debug: - pyfalog.critical("Running in frozen mode with debug turned on. Forcing all output to be written to log.") + if sys.version_info < (2, 6) or sys.version_info > (3, 0): + exit_message = "\nPyfa requires python 2.x branch ( >= 2.6 )\nExiting." + pyfalog.critical(exit_message) + raise Exception(exit_message) - from gui.mainFrame import MainFrame + if wx is None or wxversion is None: + exit_message = "\nCannot find wxPython\nYou can download wxPython (2.8+) from http://www.wxpython.org/" + pyfalog.critical(exit_message) + raise Exception(exit_message) + else: + if options.force28 is True and wxversion.checkInstalled('2.8'): + pyfalog.info("wxPython is installed. Version: {0} (forced).", wxversion.getInstalled()) + elif options.force28 is not True and (wxversion.checkInstalled('2.8') or wxversion.checkInstalled('3.0')): + pyfalog.info("wxPython is installed. Version: {0}.", wxversion.getInstalled()) + else: + exit_message = "\nInstalled wxPython version doesn't meet requirements.\nYou can download wxPython 2.8 or 3.0 from http://www.wxpython.org/" + pyfalog.critical(exit_message) + raise Exception(exit_message) + + if sqlalchemy is None: + exit_message = "\nCannot find sqlalchemy.\nYou can download sqlalchemy (0.6+) from http://www.sqlalchemy.org/" + pyfalog.critical(exit_message) + raise Exception(exit_message) + else: + saVersion = sqlalchemy.__version__ + saMatch = re.match("([0-9]+).([0-9]+)([b\.])([0-9]+)", saVersion) + if saMatch: + saMajor = int(saMatch.group(1)) + saMinor = int(saMatch.group(2)) + betaFlag = True if saMatch.group(3) == "b" else False + saBuild = int(saMatch.group(4)) if not betaFlag else 0 + if saMajor == 0 and (saMinor < 5 or (saMinor == 5 and saBuild < 8)): + pyfalog.critical("Pyfa requires sqlalchemy 0.5.8 at least but current sqlalchemy version is {0}", format(sqlalchemy.__version__)) + pyfalog.critical("You can download sqlalchemy (0.5.8+) from http://www.sqlalchemy.org/") + sys.exit(1) + else: + pyfalog.warning("Unknown sqlalchemy version string format, skipping check") + + import eos.db + # noinspection PyUnresolvedReferences + import service.prefetch # noqa: F401 + + # Make sure the saveddata db exists + if not os.path.exists(config.savePath): + os.mkdir(config.savePath) + + eos.db.saveddata_meta.create_all() + + pyfalog.info("Running in logging mode: {0}", logging_mode) + + if hasattr(sys, 'frozen') and options.debug: + pyfalog.critical("Running in frozen mode with debug turned on. Forcing all output to be written to log.") + + from gui.mainFrame import MainFrame + + except Exception as e: + tb = traceback.format_exc() + pyfa = wx.App(False) + ErrorFrame(e, tb) + pyfa.MainLoop() + pyfalog.critical("Exception in main thread.") + pyfalog.critical(tb) + raise + sys.exit() pyfa = wx.App(False) MainFrame(options.title) pyfa.MainLoop() + + # TODO: Add some thread cleanup code here. Right now we bail, and that can lead to orphaned threads or threads not properly exiting. + sys.exit()