diff --git a/config.py b/config.py
index 784e2cf54..d49b6d37e 100644
--- a/config.py
+++ b/config.py
@@ -18,10 +18,10 @@ debug = False
saveInRoot = False
# Version data
-version = "1.27.1"
+version = "1.27.2"
tag = "git"
expansionName = "YC119.2"
-expansionVersion = "1.2"
+expansionVersion = "1.4"
evemonMinVersion = "4081"
pyfaPath = None
@@ -58,6 +58,15 @@ def __createDirs(path):
os.makedirs(path)
+def getPyfaRoot():
+ base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
+ root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
+ root = unicode(root, sys.getfilesystemencoding())
+ return root
+
+def getDefaultSave():
+ return unicode(os.path.expanduser(os.path.join("~", ".pyfa")), sys.getfilesystemencoding())
+
def defPaths(customSavePath):
global debug
global pyfaPath
@@ -75,32 +84,32 @@ def defPaths(customSavePath):
# Python 2.X uses ANSI by default, so we need to convert the character encoding
pyfaPath = getattr(configforced, "pyfaPath", pyfaPath)
if pyfaPath is None:
- pyfaPath = getPyfaPath()
+ pyfaPath = getPyfaRoot()
# Where we store the saved fits etc, default is the current users home directory
if saveInRoot is True:
savePath = getattr(configforced, "savePath", None)
if savePath is None:
- savePath = getPyfaPath("saveddata")
+ savePath = os.path.join(pyfaPath, "saveddata")
else:
savePath = getattr(configforced, "savePath", None)
if savePath is None:
if customSavePath is None: # customSavePath is not overriden
- savePath = os.path.expanduser(os.path.join("~", ".pyfa"))
+ savePath = getDefaultSave()
else:
savePath = customSavePath
__createDirs(savePath)
if isFrozen():
- certName = "cacert.pem"
- os.environ["REQUESTS_CA_BUNDLE"] = getPyfaPath(certName).encode('utf8')
- os.environ["SSL_CERT_FILE"] = getPyfaPath(certName).encode('utf8')
+ os.environ["REQUESTS_CA_BUNDLE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8')
+ os.environ["SSL_CERT_FILE"] = os.path.join(pyfaPath, "cacert.pem").encode('utf8')
- loggingFormat = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s'
- logging.basicConfig(format=loggingFormat, level=logLevel)
- handler = logging.handlers.RotatingFileHandler(getSavePath("log.txt"), maxBytes=1000000, backupCount=3)
- formatter = logging.Formatter(loggingFormat)
+ _format = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s'
+ logging.basicConfig(format=_format, level=logLevel)
+ handler = logging.handlers.RotatingFileHandler(os.path.join(savePath, "log.txt"), maxBytes=1000000,
+ backupCount=3)
+ formatter = logging.Formatter(_format)
handler.setFormatter(formatter)
logging.getLogger('').addHandler(handler)
@@ -117,14 +126,14 @@ def defPaths(customSavePath):
# sys.stderr = sl
# The database where we store all the fits etc
- saveDB = getSavePath("saveddata.db")
+ saveDB = os.path.join(savePath, "saveddata.db")
# The database where the static EVE data from the datadump is kept.
# This is not the standard sqlite datadump but a modified version created by eos
# maintenance script
- gameDB = getPyfaPath("eve.db")
+ gameDB = os.path.join(pyfaPath, "eve.db")
- # DON'T MODIFY ANYTHING BELOW!
+ ## DON'T MODIFY ANYTHING BELOW ##
import eos.config
# Caching modifiers, disable all gamedata caching, its unneeded.
@@ -133,7 +142,8 @@ def defPaths(customSavePath):
eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False"
eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False"
-
+# Keeping disabled code here for now until we can determine with decent certainty that this isn't needed
+'''
def getPyfaPath(Append=None):
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
@@ -170,3 +180,4 @@ def parsePath(root, Append=None):
path = path.decode('windows-1252')
return path
+'''
\ No newline at end of file
diff --git a/eve.db b/eve.db
index 6252aada1..1c5c07a91 100644
Binary files a/eve.db and b/eve.db differ
diff --git a/gui/bitmapLoader.py b/gui/bitmapLoader.py
index cb47e24bd..9a6639481 100644
--- a/gui/bitmapLoader.py
+++ b/gui/bitmapLoader.py
@@ -20,7 +20,6 @@
import cStringIO
import os.path
import zipfile
-from config import parsePath
# noinspection PyPackageRequirements
import wx
@@ -35,7 +34,7 @@ except ImportError:
class BitmapLoader(object):
try:
- archive = zipfile.ZipFile(config.getPyfaPath('imgs.zip'), 'r')
+ archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip', 'r'))
except IOError:
archive = None
@@ -78,7 +77,7 @@ class BitmapLoader(object):
filename = "{0}.png".format(name)
if cls.archive:
- path = parsePath(location, filename)
+ path = os.path.join(location, filename)
if os.sep != "/" and os.sep in path:
path = path.replace(os.sep, "/")
@@ -89,7 +88,7 @@ class BitmapLoader(object):
except KeyError:
print("Missing icon file from zip: {0}".format(path))
else:
- path = config.getPyfaPath('imgs' + os.sep + location + os.sep + filename)
+ path = os.path.join(config.pyfaPath, 'imgs' + os.sep + location + os.sep + filename)
if os.path.exists(path):
return wx.Image(path)
diff --git a/gui/errorDialog.py b/gui/errorDialog.py
new file mode 100644
index 000000000..b9e70c851
--- /dev/null
+++ b/gui/errorDialog.py
@@ -0,0 +1,91 @@
+#===============================================================================
+# Copyright (C) 2010 Diego Duclos
+#
+# This file is part of pyfa.
+#
+# pyfa is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# pyfa is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with pyfa. If not, see .
+#===============================================================================
+
+import wx
+import sys
+import gui.utils.fonts as fonts
+import config
+
+class ErrorFrame(wx.Frame):
+
+ def __init__(self, exception, tb):
+ wx.Frame.__init__(self, None, id=wx.ID_ANY, title="pyfa error", pos=wx.DefaultPosition, size=wx.Size(500, 400), style=wx.DEFAULT_FRAME_STYLE^ wx.RESIZE_BORDER|wx.STAY_ON_TOP)
+
+ desc = "pyfa has experienced an unexpected error. Below is the " \
+ "Traceback that contains crucial information about how this " \
+ "error was triggered. Please contact the developers with " \
+ "the information provided through the EVE Online forums " \
+ "or file a GitHub issue."
+
+ self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
+
+ if 'wxMSW' in wx.PlatformInfo:
+ self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
+
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ headSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ self.headingText = wx.StaticText(self, wx.ID_ANY, "Error!", wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE)
+ self.headingText.SetFont(wx.Font(14, 74, 90, 92, False))
+
+ headSizer.Add(self.headingText, 1, wx.ALL, 5)
+ mainSizer.Add(headSizer, 0, wx.EXPAND, 5)
+
+ mainSizer.Add(wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND | wx.ALL, 5)
+
+ descSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.descText = wx.TextCtrl(self, wx.ID_ANY, desc, wx.DefaultPosition, wx.DefaultSize, wx.TE_AUTO_URL|wx.TE_MULTILINE|wx.TE_READONLY|wx.BORDER_NONE|wx.TRANSPARENT_WINDOW )
+ self.descText.SetFont(wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.NORMAL))
+ descSizer.Add(self.descText, 1, wx.ALL, 5)
+ mainSizer.Add(descSizer, 1, wx.EXPAND, 5)
+
+ self.eveForums = wx.HyperlinkCtrl(self, wx.ID_ANY, "EVE Forums Thread", "https://forums.eveonline.com/default.aspx?g=posts&t=466425",
+ wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE)
+
+ mainSizer.Add(self.eveForums, 0, wx.ALL, 2)
+
+ self.eveForums = wx.HyperlinkCtrl(self, wx.ID_ANY, "Github Issues", "https://github.com/pyfa-org/Pyfa/issues",
+ wx.DefaultPosition, wx.DefaultSize, wx.HL_DEFAULT_STYLE)
+
+ mainSizer.Add(self.eveForums, 0, wx.ALL, 2)
+
+ #mainSizer.AddSpacer((0, 5), 0, wx.EXPAND, 5)
+
+ self.errorTextCtrl = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH2|wx.TE_DONTWRAP)
+ self.errorTextCtrl.SetFont(wx.Font(8, wx.FONTFAMILY_TELETYPE, wx.NORMAL, wx.NORMAL))
+ mainSizer.Add(self.errorTextCtrl, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
+
+ self.errorTextCtrl.AppendText("pyfa root: ")
+ self.errorTextCtrl.AppendText(config.pyfaPath or "Unknown")
+ self.errorTextCtrl.AppendText('\n')
+ self.errorTextCtrl.AppendText("save path: ")
+ self.errorTextCtrl.AppendText(config.savePath or "Unknown")
+ self.errorTextCtrl.AppendText('\n')
+ self.errorTextCtrl.AppendText("fs encoding: ")
+ self.errorTextCtrl.AppendText(sys.getfilesystemencoding())
+ self.errorTextCtrl.AppendText('\n\n')
+ self.errorTextCtrl.AppendText(tb)
+
+ self.SetSizer(mainSizer)
+ mainSizer.Layout()
+ self.Layout()
+
+ self.Centre(wx.BOTH)
+
+ self.Show()
\ No newline at end of file
diff --git a/gui/graphFrame.py b/gui/graphFrame.py
index 25e203371..44ed641bf 100644
--- a/gui/graphFrame.py
+++ b/gui/graphFrame.py
@@ -29,7 +29,6 @@ import gui.mainFrame
import gui.globalEvents as GE
from gui.graph import Graph
from gui.bitmapLoader import BitmapLoader
-from config import parsePath
try:
import matplotlib as mpl
@@ -74,7 +73,7 @@ class GraphFrame(wx.Frame):
except:
cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib"))
- cache_file = parsePath(cache_dir, 'fontList.cache')
+ cache_file = path = os.path.join(cache_dir, 'fontList.cache')
if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file):
# remove matplotlib font cache, see #234
diff --git a/gui/itemStats.py b/gui/itemStats.py
index e305f1133..65fb3765e 100644
--- a/gui/itemStats.py
+++ b/gui/itemStats.py
@@ -849,7 +849,7 @@ class ItemEffects(wx.Panel):
If effect file does not exist, create it
"""
- file_ = config.getPyfaPath(os.path.join("eos", "effects", "%s.py" % event.GetText().lower()))
+ file_ = os.path.join(config.pyfaPath, "eos", "effects", "%s.py" % event.GetText().lower())
if not os.path.isfile(file_):
open(file_, 'a').close()
diff --git a/gui/shipBrowser.py b/gui/shipBrowser.py
index cf51788eb..c751cf2f3 100644
--- a/gui/shipBrowser.py
+++ b/gui/shipBrowser.py
@@ -692,7 +692,8 @@ class ShipBrowser(wx.Panel):
# set map & cache of fittings per category
for cat in self.categoryList:
itemIDs = [x.ID for x in cat.items]
- self.categoryFitCache[cat.ID] = sFit.countFitsWithShip(itemIDs) > 1
+ num = sFit.countFitsWithShip(itemIDs)
+ self.categoryFitCache[cat.ID] = num > 0
for ship in self.categoryList:
if self.filterShipsWithNoFits and not self.categoryFitCache[ship.ID]:
diff --git a/gui/utils/exportHtml.py b/gui/utils/exportHtml.py
index 802a8358b..01a2f6e30 100644
--- a/gui/utils/exportHtml.py
+++ b/gui/utils/exportHtml.py
@@ -4,7 +4,9 @@ import time
import wx
from service.settings import HTMLExportSettings
from service.fit import Fit
+from service.port import Port
from service.market import Market
+from eos.db import getFit
class exportHtml(object):
@@ -173,6 +175,7 @@ class exportHtmlThread(threading.Thread):
count = 0
+ #todo: logging for export exceptions
for group in categoryList:
# init market group string to give ships something to attach to
HTMLgroup = ''
@@ -184,6 +187,7 @@ class exportHtmlThread(threading.Thread):
groupFits = 0
for ship in ships:
fits = sFit.getFitsWithShip(ship.ID)
+
if len(fits) > 0:
groupFits += len(fits)
@@ -192,11 +196,11 @@ class exportHtmlThread(threading.Thread):
return
fit = fits[0]
try:
- dnaFit = sFit.exportDna(fit[0])
+ dnaFit = Port.exportDna(getFit(fit[0]))
HTMLgroup += '
' + ship.name + ": " + \
fit[1] + '\n'
- except:
- pass
+ except Exception, e:
+ continue
finally:
if self.callback:
wx.CallAfter(self.callback, count)
@@ -214,10 +218,11 @@ class exportHtmlThread(threading.Thread):
if self.stopRunning:
return
try:
- dnaFit = sFit.exportDna(fit[0])
+ dnaFit = Port.exportDna(getFit(fit[0]))
+ print dnaFit
HTMLship += ' ' + fit[
1] + '\n'
- except:
+ except Exception, e:
continue
finally:
if self.callback:
@@ -266,10 +271,10 @@ class exportHtmlThread(threading.Thread):
if self.stopRunning:
return
try:
- dnaFit = sFit.exportDna(fit[0])
+ dnaFit = Port.exportDna(getFit(fit[0]))
HTML += '' + ship.name + ': ' + \
fit[1] + '
\n'
- except:
+ except Exception, e:
continue
finally:
if self.callback:
diff --git a/pyfa.py b/pyfa.py
index 6453d373e..93a5c9a2e 100755
--- a/pyfa.py
+++ b/pyfa.py
@@ -114,32 +114,46 @@ if __name__ == "__main__":
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)
- config.defPaths(options.savepath)
- # Basic logging initialization
import logging
- logging.basicConfig()
-
# Import everything
# noinspection PyPackageRequirements
import wx
import os
import os.path
- import eos.db
- # noinspection PyUnresolvedReferences
- import service.prefetch # noqa: F401
+ try:
+ # convert to unicode if it is set
+ if options.savepath is not None:
+ options.savepath = unicode(options.savepath)
+ config.defPaths(options.savepath)
+
+ # Basic logging initialization
+ logging.basicConfig()
+
+ 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()
+ sys.exit()
+
from gui.mainFrame import MainFrame
- # Make sure the saveddata db exists
- if not os.path.exists(config.savePath):
- os.mkdir(config.savePath)
-
- eos.db.saveddata_meta.create_all()
-
pyfa = wx.App(False)
MainFrame(options.title)
pyfa.MainLoop()
diff --git a/service/pycrest/eve.py b/service/pycrest/eve.py
index c96a10885..367c0e1f9 100644
--- a/service/pycrest/eve.py
+++ b/service/pycrest/eve.py
@@ -43,7 +43,7 @@ class FileCache(APICache):
os.mkdir(self.path, 0o700)
def _getpath(self, key):
- return config.parsePath(self.path, str(hash(key)) + '.cache')
+ return os.path.join(self.path, str(hash(key)) + '.cache')
def put(self, key, value):
with open(self._getpath(key), 'wb') as f:
diff --git a/service/settings.py b/service/settings.py
index cf4b67b1e..d3f28e0a4 100644
--- a/service/settings.py
+++ b/service/settings.py
@@ -25,7 +25,7 @@ import config
class SettingsProvider(object):
- BASE_PATH = config.getSavePath("settings")
+ BASE_PATH = os.path.join(config.savePath, 'settings')
settings = {}
_instance = None
@@ -44,7 +44,7 @@ class SettingsProvider(object):
s = self.settings.get(area)
if s is None:
- p = config.parsePath(self.BASE_PATH, area)
+ p = os.path.join(self.BASE_PATH, area)
if not os.path.exists(p):
info = {}