From 23d9e7a91beb1178fe0268495d2960e9458afeeb Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sun, 20 May 2018 15:50:56 -0400 Subject: [PATCH 01/12] Fix travis config --- .travis.yml | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2b4dbf181..889ad5544 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,9 @@ +dist: trusty +sudo: required language: python cache: pip python: - - '2.7' + - '3.6' env: - TOXENV=pep8 addons: @@ -12,28 +14,23 @@ before_install: - pip install tox # We're not actually installing Tox, but have to run it before we install wxPython via Conda. This is fugly but vOv - tox - # get Conda - - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then - wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; - else - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; - fi - - bash miniconda.sh -b -p $HOME/miniconda - - export PATH="$HOME/miniconda/bin:$PATH" - - hash -r - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - # Useful for debugging any issues with conda - - conda info -a -install: + - pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk2/ubuntu-14.04 wxPython==4.0.0b2 +# # get Conda +# - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then +# wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; +# else +# wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; +# fi +# - bash miniconda.sh -b -p $HOME/miniconda +# - export PATH="$HOME/miniconda/bin:$PATH" +# - hash -r +# - conda config --set always_yes yes --set changeps1 no +# - conda update -q conda +# # Useful for debugging any issues with conda +# - conda info -a +#install: # install wxPython 3.0.0.0 - - conda install -c https://conda.anaconda.org/travis wxpython -before_script: - - pip install -r requirements.txt - - pip install -r requirements_test.txt + # - conda install -c https://conda.anaconda.org/travis wxpython=4.0.0b2 script: - - py.test --cov=./ -after_success: - - bash <(curl -s https://codecov.io/bash) -before_deploy: - - pip install -r requirements_build_linux.txt + - tox + From 2cac214f46e5365f77623540e3355c6d494c853c Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sun, 20 May 2018 15:55:26 -0400 Subject: [PATCH 02/12] tox --- gui/characterEditor.py | 3 --- service/server.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gui/characterEditor.py b/gui/characterEditor.py index 3fc43daa9..c0d8de298 100644 --- a/gui/characterEditor.py +++ b/gui/characterEditor.py @@ -734,9 +734,6 @@ class APIView(wx.Panel): self.stDisabledTip.Wrap(-1) hintSizer.Add(self.stDisabledTip, 0, wx.TOP | wx.BOTTOM, 10) - - - self.stDisabledTip.Hide() hintSizer.AddStretchSpacer() pmainSizer.Add(hintSizer, 0, wx.EXPAND, 5) diff --git a/service/server.py b/service/server.py index 253b0417e..09af2299e 100644 --- a/service/server.py +++ b/service/server.py @@ -3,6 +3,7 @@ import urllib.parse import socket import threading from logbook import Logger +import socketserver pyfalog = Logger(__name__) @@ -103,7 +104,6 @@ class AuthHandler(http.server.BaseHTTPRequestHandler): def log_message(self, format, *args): return -import socketserver # http://code.activestate.com/recipes/425210-simple-stoppable-server-using-socket-timeout/ class StoppableHTTPServer(socketserver.TCPServer): From aeb1a80e73b1f8357160b1b63f701c1dc09c713a Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 21 May 2018 21:11:51 -0400 Subject: [PATCH 03/12] fix attempt for #1602 --- eos/effects/adaptivearmorhardener.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/eos/effects/adaptivearmorhardener.py b/eos/effects/adaptivearmorhardener.py index 246c67fcf..81bc9412c 100644 --- a/eos/effects/adaptivearmorhardener.py +++ b/eos/effects/adaptivearmorhardener.py @@ -13,11 +13,14 @@ type = "active" def handler(fit, module, context): damagePattern = fit.damagePattern + # pyfalog.debug("==============================") static_adaptive_behavior = eos.config.settings['useStaticAdaptiveArmorHardener'] if (damagePattern.emAmount == damagePattern.thermalAmount == damagePattern.kineticAmount == damagePattern.explosiveAmount) and static_adaptive_behavior: - pyfalog.debug("Setting adaptivearmorhardener resists to uniform profile.") + # pyfalog.debug("Setting adaptivearmorhardener resists to uniform profile.") + for attr in ("armorEmDamageResonance", "armorThermalDamageResonance", "armorKineticDamageResonance", "armorExplosiveDamageResonance"): + fit.ship.multiplyItemAttr(attr, module.getModifiedItemAttr(attr), stackingPenalties=True, penaltyGroup="preMul") return # Skip if there is no damage pattern. Example: projected ships or fleet boosters @@ -30,7 +33,7 @@ def handler(fit, module, context): damagePattern.kineticAmount * fit.ship.getModifiedItemAttr('armorKineticDamageResonance'), damagePattern.explosiveAmount * fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance'), ) - # pyfalog.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f", baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3]) + # pyfalog.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f" % (baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])) resistanceShiftAmount = module.getModifiedItemAttr( 'resistanceShiftAmount') / 100 # The attribute is in percent and we want a fraction @@ -46,7 +49,7 @@ def handler(fit, module, context): cycleList = [] loopStart = -20 for num in range(50): - # pyfalog.debug("Starting cycle %d.", num) + # pyfalog.debug("Starting cycle %d." % num) # The strange order is to emulate the ingame sorting when different types have taken the same amount of damage. # This doesn't take into account stacking penalties. In a few cases fitting a Damage Control causes an inaccurate result. damagePattern_tuples = [ @@ -84,7 +87,7 @@ def handler(fit, module, context): RAHResistance[sortedDamagePattern_tuples[1][0]] = sortedDamagePattern_tuples[1][2] + change1 RAHResistance[sortedDamagePattern_tuples[2][0]] = sortedDamagePattern_tuples[2][2] + change2 RAHResistance[sortedDamagePattern_tuples[3][0]] = sortedDamagePattern_tuples[3][2] + change3 - # pyfalog.debug("Resistances shifted to %f/%f/%f/%f", RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3]) + # pyfalog.debug("Resistances shifted to %f/%f/%f/%f" % ( RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3])) # See if the current RAH profile has been encountered before, indicating a loop. for i, val in enumerate(cycleList): @@ -94,7 +97,7 @@ def handler(fit, module, context): abs(RAHResistance[2] - val[2]) <= tolerance and \ abs(RAHResistance[3] - val[3]) <= tolerance: loopStart = i - # pyfalog.debug("Loop found: %d-%d", loopStart, num) + # pyfalog.debug("Loop found: %d-%d" % (loopStart, num)) break if loopStart >= 0: break @@ -102,8 +105,8 @@ def handler(fit, module, context): cycleList.append(list(RAHResistance)) if loopStart < 0: - pyfalog.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: {0}/{1}/{2}/{3}", - baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3]) + # pyfalog.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: {0}/{1}/{2}/{3}".format( + baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])) # Average the profiles in the RAH loop, or the last 20 if it didn't find a loop. loopCycles = cycleList[loopStart:] @@ -117,7 +120,7 @@ def handler(fit, module, context): average[i] = round(average[i] / numCycles, 3) # Set the new resistances - # pyfalog.debug("Setting new resist profile: %f/%f/%f/%f", average[0], average[1], average[2],average[3]) + # pyfalog.debug("Setting new resist profile: %f/%f/%f/%f" % ( average[0], average[1], average[2],average[3])) for i, attr in enumerate(( 'armorEmDamageResonance', 'armorThermalDamageResonance', 'armorKineticDamageResonance', 'armorExplosiveDamageResonance')): From 6b346c4b37a97413380deecebcd40209adaa5cc9 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 21 May 2018 22:08:56 -0400 Subject: [PATCH 04/12] Whoops --- eos/effects/adaptivearmorhardener.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eos/effects/adaptivearmorhardener.py b/eos/effects/adaptivearmorhardener.py index 81bc9412c..90035a5db 100644 --- a/eos/effects/adaptivearmorhardener.py +++ b/eos/effects/adaptivearmorhardener.py @@ -106,7 +106,7 @@ def handler(fit, module, context): if loopStart < 0: # pyfalog.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: {0}/{1}/{2}/{3}".format( - baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])) + # baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])) # Average the profiles in the RAH loop, or the last 20 if it didn't find a loop. loopCycles = cycleList[loopStart:] From fde449c7d8734b6091fda0f1b816d5533a9a426d Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 21 May 2018 22:09:30 -0400 Subject: [PATCH 05/12] more whoops --- eos/effects/adaptivearmorhardener.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eos/effects/adaptivearmorhardener.py b/eos/effects/adaptivearmorhardener.py index 90035a5db..25a4335a6 100644 --- a/eos/effects/adaptivearmorhardener.py +++ b/eos/effects/adaptivearmorhardener.py @@ -104,7 +104,7 @@ def handler(fit, module, context): cycleList.append(list(RAHResistance)) - if loopStart < 0: + # if loopStart < 0: # pyfalog.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: {0}/{1}/{2}/{3}".format( # baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])) From f9e60a00f2f528e6f7839613f72dfc9714a64f61 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 21 May 2018 23:03:25 -0400 Subject: [PATCH 06/12] Remove the CREST table from a migration, since it no longer exist (was causing issues for some folks with very old databases) --- eos/db/migrations/upgrade22.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eos/db/migrations/upgrade22.py b/eos/db/migrations/upgrade22.py index 568351a25..5a9b01e34 100644 --- a/eos/db/migrations/upgrade22.py +++ b/eos/db/migrations/upgrade22.py @@ -14,7 +14,7 @@ def upgrade(saveddata_engine): "boosters": 2, "cargo": 2, "characters": 2, - "crest": 1, + # "crest": 1, "damagePatterns": 2, "drones": 2, "fighters": 2, From 2f9d2e2a607fedad3714bb5a574773beebaf4b26 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 21 May 2018 23:15:41 -0400 Subject: [PATCH 07/12] Force command processors not to show (#1562) --- gui/builtinMarketBrowser/marketTree.py | 1 + service/market.py | 1 + 2 files changed, 2 insertions(+) diff --git a/gui/builtinMarketBrowser/marketTree.py b/gui/builtinMarketBrowser/marketTree.py index 8b1286e50..f6c62732c 100644 --- a/gui/builtinMarketBrowser/marketTree.py +++ b/gui/builtinMarketBrowser/marketTree.py @@ -53,6 +53,7 @@ class MarketTree(wx.TreeCtrl): # And add real market group contents sMkt = self.sMkt currentMktGrp = sMkt.getMarketGroup(self.GetItemData(root), eager="children") + for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp): # If market should have items but it doesn't, do not show it if sMkt.marketGroupValidityCheck(childMktGrp) is False: diff --git a/service/market.py b/service/market.py index dd2d60d14..b1fc64fb2 100644 --- a/service/market.py +++ b/service/market.py @@ -318,6 +318,7 @@ class Market(object): self.FORCEDMARKETGROUP = { 685: False, # Ship Equipment > Electronic Warfare > ECCM 681: False, # Ship Equipment > Electronic Warfare > Sensor Backup Arrays + 1639: False # Ship Equipment > Fleet Assistance > Command Processors } # Misc definitions From 9f69c7638011bff2e7e2ce0ac1a3acef0cd4aa61 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 21 May 2018 23:23:21 -0400 Subject: [PATCH 08/12] Reimplement support for exporting ESI fittings... whoops (#1593) --- gui/esiFittings.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gui/esiFittings.py b/gui/esiFittings.py index ca04387e5..993b95f37 100644 --- a/gui/esiFittings.py +++ b/gui/esiFittings.py @@ -231,6 +231,7 @@ class ExportToEve(wx.Frame): return self.charChoice.GetClientData(selection) if selection is not None else None def exportFitting(self, event): + sPort = Port.getInstance() fitID = self.mainFrame.getActiveFit() self.statusbar.SetStatusText("", 0) @@ -240,9 +241,12 @@ class ExportToEve(wx.Frame): return self.statusbar.SetStatusText("Sending request and awaiting response", 1) + sEsi = Esi.getInstance() try: - + sFit = Fit.getInstance() + data = sPort.exportESI(sFit.getFit(fitID)) + res = sEsi.postFitting(self.getActiveCharacter(), data) self.statusbar.SetStatusText("", 0) self.statusbar.SetStatusText("", 1) # try: From eaae51f8d815bb23bce803e65698394fbe5fa309 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Mon, 21 May 2018 23:36:40 -0400 Subject: [PATCH 09/12] Add status messages back to ESI fitting export (#1502) --- gui/esiFittings.py | 28 +++++++++++++++------------- service/esi.py | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/gui/esiFittings.py b/gui/esiFittings.py index 993b95f37..99d8f33eb 100644 --- a/gui/esiFittings.py +++ b/gui/esiFittings.py @@ -243,28 +243,30 @@ class ExportToEve(wx.Frame): self.statusbar.SetStatusText("Sending request and awaiting response", 1) sEsi = Esi.getInstance() + sFit = Fit.getInstance() + data = sPort.exportESI(sFit.getFit(fitID)) + res = sEsi.postFitting(self.getActiveCharacter(), data) + try: - sFit = Fit.getInstance() - data = sPort.exportESI(sFit.getFit(fitID)) - res = sEsi.postFitting(self.getActiveCharacter(), data) + res.raise_for_status() self.statusbar.SetStatusText("", 0) - self.statusbar.SetStatusText("", 1) - # try: - # text = json.loads(res.text) - # self.statusbar.SetStatusText(text['message'], 1) - # except ValueError: - # pyfalog.warning("Value error on loading JSON.") - # self.statusbar.SetStatusText("", 1) + self.statusbar.SetStatusText(res.reason, 1) except requests.exceptions.ConnectionError: msg = "Connection error, please check your internet connection" pyfalog.error(msg) - self.statusbar.SetStatusText(msg) + self.statusbar.SetStatusText("ERROR", 0) + self.statusbar.SetStatusText(msg, 1) except ESIExportException as ex: pyfalog.error(ex) self.statusbar.SetStatusText("ERROR", 0) - self.statusbar.SetStatusText(ex.args[0], 1) + self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1) except APIException as ex: - ESIExceptionHandler(self, ex) + try: + ESIExceptionHandler(self, ex) + except Exception as ex: + self.statusbar.SetStatusText("ERROR", 0) + self.statusbar.SetStatusText("{} - {}".format(res.status_code, res.reason), 1) + pyfalog.error(ex) class SsoCharacterMgmt(wx.Dialog): diff --git a/service/esi.py b/service/esi.py index 2ccd460b0..4b5f8198f 100644 --- a/service/esi.py +++ b/service/esi.py @@ -96,7 +96,7 @@ class Esi(EsiAccess): # @todo: new fitting ID can be recovered from resp.data, char = self.getSsoCharacter(id) resp = super().postFitting(char, json_str) - return resp.json() + return resp def delFitting(self, id, fittingID): char = self.getSsoCharacter(id) From c4177f891168ac22a319583af027cf2d1e364238 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Tue, 22 May 2018 00:06:06 -0400 Subject: [PATCH 10/12] Remove .zip check for img files (no longer part of build, wondering if this is causing slow start up times) --- gui/bitmap_loader.py | 15 +++++++++------ gui/mainFrame.py | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/gui/bitmap_loader.py b/gui/bitmap_loader.py index 9330f1fc3..c7ad7c548 100644 --- a/gui/bitmap_loader.py +++ b/gui/bitmap_loader.py @@ -32,12 +32,15 @@ logging = Logger(__name__) class BitmapLoader(object): - try: - archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r') - logging.info("Using zipped image files.") - except (IOError, TypeError): - logging.info("Using local image files.") - archive = None + # try: + # archive = zipfile.ZipFile(os.path.join(config.pyfaPath, 'imgs.zip'), 'r') + # logging.info("Using zipped image files.") + # except (IOError, TypeError): + # logging.info("Using local image files.") + # archive = None + + logging.info("Using local image files.") + archive = None cached_bitmaps = OrderedDict() dont_use_cached_bitmaps = False diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 4a8a6d1a1..e526ce8cd 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -98,6 +98,8 @@ except ImportError as e: pyfalog = Logger(__name__) +pyfalog.debug("Done loading mainframe imports") + # dummy panel(no paint no erasebk) class PFPanel(wx.Panel): From be21fec2d22bd037899241535562c217178b2987 Mon Sep 17 00:00:00 2001 From: Alexey Min Date: Sat, 26 May 2018 14:34:40 +0300 Subject: [PATCH 11/12] Make item traits copyable --- gui/builtinItemStatsViews/itemTraits.py | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/gui/builtinItemStatsViews/itemTraits.py b/gui/builtinItemStatsViews/itemTraits.py index 12abd078d..1ea0514a5 100644 --- a/gui/builtinItemStatsViews/itemTraits.py +++ b/gui/builtinItemStatsViews/itemTraits.py @@ -13,5 +13,38 @@ class ItemTraits(wx.Panel): self.traits = wx.html.HtmlWindow(self) self.traits.SetPage(item.traits.traitText) + self.traits.Bind(wx.EVT_CONTEXT_MENU, self.onPopupMenu) + self.traits.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) + mainSizer.Add(self.traits, 1, wx.ALL | wx.EXPAND, 0) self.Layout() + + self.popupMenu = wx.Menu() + copyItem = wx.MenuItem(self.popupMenu, 1, 'Copy') + self.popupMenu.Append(copyItem) + self.popupMenu.Bind(wx.EVT_MENU, self.menuClickHandler, copyItem) + + def onPopupMenu(self, event): + self.PopupMenu(self.popupMenu) + + def menuClickHandler(self, event): + selectedMenuItem = event.GetId() + if selectedMenuItem == 1: # Copy was chosen + self.copySelectionToClipboard() + + def onKeyDown(self, event): + keyCode = event.GetKeyCode() + # Ctrl + C + if keyCode == 67 and event.ControlDown(): + self.copySelectionToClipboard() + # Ctrl + A + if keyCode == 65 and event.ControlDown(): + self.traits.SelectAll() + + def copySelectionToClipboard(self): + selectedText = self.traits.SelectionToText() + if selectedText == '': # if no selection, copy all content + selectedText = self.traits.ToText() + if wx.TheClipboard.Open(): + wx.TheClipboard.SetData(wx.TextDataObject(selectedText)) + wx.TheClipboard.Close() From 8cb592db6f960157496b11f21347db40a7e87c5f Mon Sep 17 00:00:00 2001 From: Alexey Min Date: Sat, 26 May 2018 14:34:54 +0300 Subject: [PATCH 12/12] Make item description copyable --- gui/builtinItemStatsViews/itemDescription.py | 33 ++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/gui/builtinItemStatsViews/itemDescription.py b/gui/builtinItemStatsViews/itemDescription.py index ddf30dfb4..b03b892df 100644 --- a/gui/builtinItemStatsViews/itemDescription.py +++ b/gui/builtinItemStatsViews/itemDescription.py @@ -31,3 +31,36 @@ class ItemDescription(wx.Panel): mainSizer.Add(self.description, 1, wx.ALL | wx.EXPAND, 0) self.Layout() + + self.description.Bind(wx.EVT_CONTEXT_MENU, self.onPopupMenu) + self.description.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) + + self.popupMenu = wx.Menu() + copyItem = wx.MenuItem(self.popupMenu, 1, 'Copy') + self.popupMenu.Append(copyItem) + self.popupMenu.Bind(wx.EVT_MENU, self.menuClickHandler, copyItem) + + def onPopupMenu(self, event): + self.PopupMenu(self.popupMenu) + + def menuClickHandler(self, event): + selectedMenuItem = event.GetId() + if selectedMenuItem == 1: # Copy was chosen + self.copySelectionToClipboard() + + def onKeyDown(self, event): + keyCode = event.GetKeyCode() + # Ctrl + C + if keyCode == 67 and event.ControlDown(): + self.copySelectionToClipboard() + # Ctrl + A + if keyCode == 65 and event.ControlDown(): + self.description.SelectAll() + + def copySelectionToClipboard(self): + selectedText = self.description.SelectionToText() + if selectedText == '': # if no selection, copy all content + selectedText = self.description.ToText() + if wx.TheClipboard.Open(): + wx.TheClipboard.SetData(wx.TextDataObject(selectedText)) + wx.TheClipboard.Close()