diff --git a/config.py b/config.py index 24adc62c7..818c25b9f 100644 --- a/config.py +++ b/config.py @@ -24,7 +24,7 @@ saveInRoot = False # Version data -version = "2.0.1" +version = "2.0.2" tag = "Stable" expansionName = "YC120.3" expansionVersion = "1.8" diff --git a/eos/db/saveddata/character.py b/eos/db/saveddata/character.py index 739a34a98..850c41c6e 100644 --- a/eos/db/saveddata/character.py +++ b/eos/db/saveddata/character.py @@ -29,9 +29,6 @@ from eos.saveddata.user import User from eos.saveddata.character import Character, Skill from eos.saveddata.ssocharacter import SsoCharacter - - - characters_table = Table("characters", saveddata_meta, Column("ID", Integer, primary_key=True), Column("name", String, nullable=False), diff --git a/eos/effects/structurerigaoevelocitybonussingletargetmissiles.py b/eos/effects/structurerigaoevelocitybonussingletargetmissiles.py index 6d4503ec7..2bf5f4af0 100644 --- a/eos/effects/structurerigaoevelocitybonussingletargetmissiles.py +++ b/eos/effects/structurerigaoevelocitybonussingletargetmissiles.py @@ -5,6 +5,6 @@ type = "passive" def handler(fit, src, context): groups = ("Structure Anti-Subcapital Missile", "Structure Anti-Capital Missile") - fit.modules.filteredItemBoost(lambda mod: mod.charge.group.name in groups, + fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups, "aoeVelocity", src.getModifiedItemAttr("structureRigMissileExploVeloBonus"), stackingPenalties=True) diff --git a/eos/effects/structurerigvelocitybonussingletargetmissiles.py b/eos/effects/structurerigvelocitybonussingletargetmissiles.py index 1af82afd0..929cc7a3e 100644 --- a/eos/effects/structurerigvelocitybonussingletargetmissiles.py +++ b/eos/effects/structurerigvelocitybonussingletargetmissiles.py @@ -4,6 +4,6 @@ type = "passive" def handler(fit, src, context): groups = ("Structure Anti-Subcapital Missile", "Structure Anti-Capital Missile") - fit.modules.filteredItemBoost(lambda mod: mod.charge.group.name in groups, + fit.modules.filteredChargeBoost(lambda mod: mod.charge.group.name in groups, "maxVelocity", src.getModifiedItemAttr("structureRigMissileVelocityBonus"), stackingPenalties=True) diff --git a/eos/effects/warpscrambleblockmwdwithnpceffect.py b/eos/effects/warpscrambleblockmwdwithnpceffect.py index d96a9f5d3..0985d4673 100644 --- a/eos/effects/warpscrambleblockmwdwithnpceffect.py +++ b/eos/effects/warpscrambleblockmwdwithnpceffect.py @@ -17,8 +17,8 @@ def handler(fit, module, context): # this is such a dirty hack for mod in fit.modules: if not mod.isEmpty and mod.state > State.ONLINE and ( - mod.item.requiresSkill("Micro Jump Drive Operation") - or mod.item.requiresSkill("High Speed Maneuvering") + mod.item.requiresSkill("Micro Jump Drive Operation") or + mod.item.requiresSkill("High Speed Maneuvering") ): mod.state = State.ONLINE if not mod.isEmpty and mod.item.requiresSkill("Micro Jump Drive Operation") and mod.state > State.ONLINE: diff --git a/eos/saveddata/character.py b/eos/saveddata/character.py index 55edd9121..9edb866e8 100644 --- a/eos/saveddata/character.py +++ b/eos/saveddata/character.py @@ -170,7 +170,6 @@ class Character(object): if x.client == clientHash: self.__ssoCharacters.remove(x) - def getSsoCharacter(self, clientHash): return next((x for x in self.__ssoCharacters if x.client == clientHash), None) diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index 185ec50e4..cf669f273 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -144,10 +144,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): return empty @classmethod - def buildRack(cls, slot): + def buildRack(cls, slot, num=None): empty = Rack(None) empty.__slot = slot empty.dummySlot = slot + empty.num = num return empty @property @@ -801,6 +802,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): class Rack(Module): """ This is simply the Module class named something else to differentiate - it for app logic. This class does not do anything special + it for app logic. The only thing interesting about it is the num property, + which is the number of slots for this rack """ - pass + num = None diff --git a/eos/saveddata/ssocharacter.py b/eos/saveddata/ssocharacter.py index d1234c2c4..04b57bdc9 100644 --- a/eos/saveddata/ssocharacter.py +++ b/eos/saveddata/ssocharacter.py @@ -33,7 +33,6 @@ class SsoCharacter(object): self.refreshToken = refreshToken self.accessTokenExpires = None - @reconstructor def init(self): pass diff --git a/gui/builtinContextMenus/moduleAmmoPicker.py b/gui/builtinContextMenus/moduleAmmoPicker.py index 47a6fc87d..69b5e43b8 100644 --- a/gui/builtinContextMenus/moduleAmmoPicker.py +++ b/gui/builtinContextMenus/moduleAmmoPicker.py @@ -58,9 +58,9 @@ class ModuleAmmoPicker(ContextMenu): def turretSorter(self, charge): damage = 0 - range_ = (self.module.getModifiedItemAttr("maxRange")) * \ + range_ = (self.module.item.getAttribute("maxRange")) * \ (charge.getAttribute("weaponRangeMultiplier") or 1) - falloff = (self.module.getModifiedItemAttr("falloff")) * \ + falloff = (self.module.item.getAttribute("falloff")) * \ (charge.getAttribute("fallofMultiplier") or 1) for type_ in self.DAMAGE_TYPES: d = charge.getAttribute("%sDamage" % type_) diff --git a/gui/builtinPreferenceViews/pyfaEsiPreferences.py b/gui/builtinPreferenceViews/pyfaEsiPreferences.py index ef81b7480..7eaf31a4e 100644 --- a/gui/builtinPreferenceViews/pyfaEsiPreferences.py +++ b/gui/builtinPreferenceViews/pyfaEsiPreferences.py @@ -43,13 +43,17 @@ class PFEsiPref(PreferenceView): rbSizer = wx.BoxSizer(wx.HORIZONTAL) self.rbMode = wx.RadioBox(panel, -1, "Login Authentication Method", wx.DefaultPosition, wx.DefaultSize, ['Local Server', 'Manual'], 1, wx.RA_SPECIFY_COLS) - self.rbMode.SetItemToolTip(0, "This options starts a local webserver that the web application will call back to with information about the character login.") - self.rbMode.SetItemToolTip(1, "This option prompts users to copy and paste information from the web application to allow for character login. Use this if having issues with the local server.") + self.rbMode.SetItemToolTip(0, "This options starts a local webserver that the web application will call back to" + " with information about the character login.") + self.rbMode.SetItemToolTip(1, "This option prompts users to copy and paste information from the web application " + "to allow for character login. Use this if having issues with the local server.") self.rbSsoMode = wx.RadioBox(panel, -1, "SSO Mode", wx.DefaultPosition, wx.DefaultSize, ['pyfa.io', 'Custom application'], 1, wx.RA_SPECIFY_COLS) - self.rbSsoMode.SetItemToolTip(0, "This options routes SSO Logins through pyfa.io, allowing you to easily login without any configuration. When in doubt, use this option.") - self.rbSsoMode.SetItemToolTip(1, "This option goes through EVE SSO directly, but requires more configuration. Use this is pyfa.io is blocked for some reason, or if you do not wish to route data throguh pyfa.io.") + self.rbSsoMode.SetItemToolTip(0, "This options routes SSO Logins through pyfa.io, allowing you to easily login " + "without any configuration. When in doubt, use this option.") + self.rbSsoMode.SetItemToolTip(1, "This option goes through EVE SSO directly, but requires more configuration. Use " + "this is pyfa.io is blocked for some reason, or if you do not wish to route data throguh pyfa.io.") self.rbMode.SetSelection(self.settings.get('loginMode')) self.rbSsoMode.SetSelection(self.settings.get('ssoMode')) @@ -70,12 +74,6 @@ class PFEsiPref(PreferenceView): mainSizer.Add(wx.StaticLine(panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND, 5) - # self.stInfo = wx.StaticText(panel, wx.ID_ANY, - # u"Using custom applications details will let pyfa to access the SSO under your application, rather than the pyfa application that is automatically set up. This requires you to set up your own ESI client application and accept CCPs License Agreement. Additionally, when setting up your client, make sure the callback url is set to 'http://localhost:6461'. Please see the pyfa wiki for more information regarding this", - # wx.DefaultPosition, wx.DefaultSize, 0) - # self.stInfo.Wrap(dlgWidth) - # mainSizer.Add(self.stInfo, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) - fgAddrSizer = wx.FlexGridSizer(2, 2, 0, 0) fgAddrSizer.AddGrowableCol(1) fgAddrSizer.SetFlexibleDirection(wx.BOTH) @@ -105,10 +103,6 @@ class PFEsiPref(PreferenceView): mainSizer.Add(fgAddrSizer, 0, wx.EXPAND, 5) - - - timeoutSizer = wx.BoxSizer(wx.HORIZONTAL) - # self.stTimout = wx.StaticText(panel, wx.ID_ANY, "Timeout (seconds):", wx.DefaultPosition, wx.DefaultSize, 0) # self.stTimout.Wrap(-1) # diff --git a/gui/builtinPreferenceViews/pyfaNetworkPreferences.py b/gui/builtinPreferenceViews/pyfaNetworkPreferences.py index 4f9887f8a..526dc0930 100644 --- a/gui/builtinPreferenceViews/pyfaNetworkPreferences.py +++ b/gui/builtinPreferenceViews/pyfaNetworkPreferences.py @@ -150,10 +150,10 @@ class PFNetworkPref(PreferenceView): proxy = self.settings.autodetect() if proxy is not None: - addr, port = proxy - txt = addr + ":" + str(port) + addr, port = proxy + txt = addr + ":" + str(port) else: - txt = "None" + txt = "None" self.stPSAutoDetected.SetLabel("Auto-detected: " + txt) self.stPSAutoDetected.Disable() diff --git a/gui/builtinStatsViews/firepowerViewFull.py b/gui/builtinStatsViews/firepowerViewFull.py index 98d54d714..29ce7a482 100644 --- a/gui/builtinStatsViews/firepowerViewFull.py +++ b/gui/builtinStatsViews/firepowerViewFull.py @@ -129,7 +129,7 @@ class FirepowerViewFull(StatsView): # Remove effective label hsizer = self.headerPanel.GetSizer() hsizer.Hide(self.stEff) - #self.stEff.Destroy() + # self.stEff.Destroy() # Get the new view view = StatsView.getView("miningyieldViewFull")(self.parent) diff --git a/gui/builtinViewColumns/baseName.py b/gui/builtinViewColumns/baseName.py index 8ed1466ac..0628eb2ad 100644 --- a/gui/builtinViewColumns/baseName.py +++ b/gui/builtinViewColumns/baseName.py @@ -73,7 +73,7 @@ class BaseName(ViewColumn): if stuff.slot == Slot.MODE: return '─ Tactical Mode ─' else: - return '─ {} Slots ─'.format(Slot.getName(stuff.slot).capitalize()) + return '─ {} {} Slot{}─'.format(stuff.num, Slot.getName(stuff.slot).capitalize(), '' if stuff.num == 1 else 's') else: return "" elif isinstance(stuff, Module): diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 9e4e65904..4db377ddb 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -222,12 +222,15 @@ class FittingView(d.Display): wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) def Destroy(self): + # @todo: when wxPython 4.0.2 is release, https://github.com/pyfa-org/Pyfa/issues/1586#issuecomment-390074915 + # Make sure to remove the shitty checks that I have to put in place for these handlers to ignore when self is None print("+++++ Destroy " + repr(self)) - print(self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED)) - print(self.mainFrame.Unbind(GE.FIT_CHANGED)) - print(self.mainFrame.Unbind(EVT_FIT_RENAMED)) - print(self.mainFrame.Unbind(EVT_FIT_REMOVED)) - print(self.mainFrame.Unbind(ITEM_SELECTED)) + + # print(self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED)) + # print(self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.fitChanged)) + # print(self.mainFrame.Unbind(EVT_FIT_RENAMED, handler=self.fitRenamed )) + # print(self.mainFrame.Unbind(EVT_FIT_REMOVED, handler=self.fitRemoved)) + # print(self.mainFrame.Unbind(ITEM_SELECTED, handler=self.appendItem)) d.Display.Destroy(self) @@ -291,6 +294,9 @@ class FittingView(d.Display): """ print('_+_+_+_+_+_ Fit Removed: {} {} activeFitID: {}, eventFitID: {}'.format(repr(self), str(bool(self)), self.activeFitID, event.fitID)) pyfalog.debug("FittingView::fitRemoved") + if not self: + event.Skip() + return if event.fitID == self.getActiveFit(): pyfalog.debug(" Deleted fit is currently active") self.parent.DeletePage(self.parent.GetPageIndex(self)) @@ -311,6 +317,9 @@ class FittingView(d.Display): event.Skip() def fitRenamed(self, event): + if not self: + event.Skip() + return fitID = event.fitID if fitID == self.getActiveFit(): self.updateTab() @@ -347,6 +356,9 @@ class FittingView(d.Display): self.parent.SetPageTextIcon(pageIndex, text, bitmap) def appendItem(self, event): + if not self: + event.Skip() + return if self.parent.IsActive(self): itemID = event.itemID fitID = self.activeFitID @@ -508,7 +520,7 @@ class FittingView(d.Display): # second loop modifies self.mods, rewrites self.blanks to represent actual index of blanks for i, (x, slot) in enumerate(self.blanks): self.blanks[i] = x + i # modify blanks with actual index - self.mods.insert(x + i, Rack.buildRack(slot)) + self.mods.insert(x + i, Rack.buildRack(slot, sum(m.slot == slot for m in self.mods))) if fit.mode: # Modes are special snowflakes and need a little manual loving @@ -516,7 +528,7 @@ class FittingView(d.Display): # while also marking the mode header position in the Blanks list if sFit.serviceFittingOptions["rackSlots"]: self.blanks.append(len(self.mods)) - self.mods.append(Rack.buildRack(Slot.MODE)) + self.mods.append(Rack.buildRack(Slot.MODE, None)) self.mods.append(fit.mode) else: @@ -528,7 +540,9 @@ class FittingView(d.Display): def fitChanged(self, event): print('====== Fit Changed: {} {} activeFitID: {}, eventFitID: {}'.format(repr(self), str(bool(self)), self.activeFitID, event.fitID)) - + if not self: + event.Skip() + return try: if self.activeFitID is not None and self.activeFitID == event.fitID: self.generateMods() diff --git a/gui/characterEditor.py b/gui/characterEditor.py index f7520e42c..3fc43daa9 100644 --- a/gui/characterEditor.py +++ b/gui/characterEditor.py @@ -734,17 +734,14 @@ class APIView(wx.Panel): self.stDisabledTip.Wrap(-1) hintSizer.Add(self.stDisabledTip, 0, wx.TOP | wx.BOTTOM, 10) - self.noCharactersTip = wx.StaticText(self, wx.ID_ANY, - "You haven't logging into EVE SSO with any characters yet. Please use the " - "button below to log into EVE.", style=wx.ALIGN_CENTER) - self.noCharactersTip.Wrap(-1) - hintSizer.Add(self.noCharactersTip, 0, wx.TOP | wx.BOTTOM, 10) + + self.stDisabledTip.Hide() hintSizer.AddStretchSpacer() pmainSizer.Add(hintSizer, 0, wx.EXPAND, 5) - fgSizerInput = wx.FlexGridSizer(3, 2, 0, 0) + fgSizerInput = wx.FlexGridSizer(1, 3, 0, 0) fgSizerInput.AddGrowableCol(1) fgSizerInput.SetFlexibleDirection(wx.BOTH) fgSizerInput.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED) @@ -754,15 +751,28 @@ class APIView(wx.Panel): fgSizerInput.Add(self.m_staticCharText, 0, wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, 10) self.charChoice = wx.Choice(self, wx.ID_ANY, style=0) - fgSizerInput.Add(self.charChoice, 1, wx.ALL | wx.EXPAND, 10) + fgSizerInput.Add(self.charChoice, 1, wx.TOP | wx.BOTTOM | wx.EXPAND, 10) + + self.fetchButton = wx.Button(self, wx.ID_ANY, "Get Skills", wx.DefaultPosition, wx.DefaultSize, 0) + self.fetchButton.Bind(wx.EVT_BUTTON, self.fetchSkills) + fgSizerInput.Add(self.fetchButton, 0, wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, 10) pmainSizer.Add(fgSizerInput, 0, wx.EXPAND, 5) + pmainSizer.AddStretchSpacer() + + self.m_staticline1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) + pmainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.ALL, 10) + + self.noCharactersTip = wx.StaticText(self, wx.ID_ANY, "Don't see your EVE character in the list?", style=wx.ALIGN_CENTER) + + self.noCharactersTip.Wrap(-1) + pmainSizer.Add(self.noCharactersTip, 0, wx.CENTER | wx.TOP | wx.BOTTOM, 0) + self.addButton = wx.Button(self, wx.ID_ANY, "Log In with EVE SSO", wx.DefaultPosition, wx.DefaultSize, 0) self.addButton.Bind(wx.EVT_BUTTON, self.addCharacter) - pmainSizer.Add(self.addButton, 0, wx.ALL | wx.ALIGN_CENTER, 5) - self.stStatus = wx.StaticText(self, wx.ID_ANY, wx.EmptyString) - pmainSizer.Add(self.stStatus, 0, wx.ALL, 5) + pmainSizer.Add(self.addButton, 0, wx.ALL | wx.ALIGN_CENTER, 10) + self.charEditor.mainFrame.Bind(GE.EVT_SSO_LOGOUT, self.ssoListChanged) self.charEditor.mainFrame.Bind(GE.EVT_SSO_LOGIN, self.ssoListChanged) self.charEditor.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged) @@ -776,9 +786,18 @@ class APIView(wx.Panel): def ssoCharChanged(self, event): sChar = Character.getInstance() activeChar = self.charEditor.entityEditor.getActiveEntity() - sChar.setSsoCharacter(activeChar.ID, self.getActiveCharacter()) + ssoChar = self.getActiveCharacter() + sChar.setSsoCharacter(activeChar.ID, ssoChar) + + self.fetchButton.Enable(ssoChar is not None) + event.Skip() + def fetchSkills(self, evt): + sChar = Character.getInstance() + char = self.charEditor.entityEditor.getActiveEntity() + sChar.apiFetch(char.ID, self.__fetchCallback) + def addCharacter(self, event): sEsi = Esi.getInstance() sEsi.login() @@ -790,17 +809,6 @@ class APIView(wx.Panel): def ssoListChanged(self, event): if not self: # todo: fix event not unbinding properly return - sEsi = Esi.getInstance() - ssoChars = sEsi.getSsoCharacters() - - if len(ssoChars) == 0: - self.charChoice.Hide() - self.m_staticCharText.Hide() - self.noCharactersTip.Show() - else: - self.noCharactersTip.Hide() - self.m_staticCharText.Show() - self.charChoice.Show() self.charChanged(event) @@ -816,6 +824,8 @@ class APIView(wx.Panel): sso = sChar.getSsoCharacter(activeChar.ID) + self.fetchButton.Enable(sso is not None) + ssoChars = sEsi.getSsoCharacters() self.charChoice.Clear() @@ -827,9 +837,9 @@ class APIView(wx.Panel): if sso is not None and char.ID == sso.ID: self.charChoice.SetSelection(currId) - if sso is None: - self.charChoice.SetSelection(noneID) + if sso is None: + self.charChoice.SetSelection(noneID) # # if chars: @@ -853,13 +863,17 @@ class APIView(wx.Panel): event.Skip() def __fetchCallback(self, e=None): - charName = self.charChoice.GetString(self.charChoice.GetSelection()) - if e is None: - self.stStatus.SetLabel("Successfully fetched {}\'s skills from EVE API.".format(charName)) - else: + if e: exc_type, exc_obj, exc_trace = e - pyfalog.error("Unable to retrieve {0}\'s skills. Error message:\n{1}".format(charName, exc_obj)) - self.stStatus.SetLabel("Unable to retrieve {}\'s skills. Error message:\n{}".format(charName, exc_obj)) + pyfalog.warn("Error fetching skill information for character") + pyfalog.warn(exc_obj) + + wx.MessageBox( + "Error fetching skill information", + "Error", wx.ICON_ERROR | wx.STAY_ON_TOP) + else: + wx.MessageBox( + "Successfully fetched skills", "Success", wx.ICON_INFORMATION | wx.STAY_ON_TOP) class SecStatusDialog(wx.Dialog): diff --git a/gui/characterSelection.py b/gui/characterSelection.py index cc63a1f82..051ce69b4 100644 --- a/gui/characterSelection.py +++ b/gui/characterSelection.py @@ -170,7 +170,6 @@ class CharacterSelection(wx.Panel): def charChanged(self, event): fitID = self.mainFrame.getActiveFit() charID = self.getActiveCharacter() - sChar = Character.getInstance() if charID == -1: # revert to previous character diff --git a/gui/chrome_tabs.py b/gui/chrome_tabs.py index c03edacab..10354b9be 100644 --- a/gui/chrome_tabs.py +++ b/gui/chrome_tabs.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # # ToDo: Bug - when selecting close on a tab, sometimes the tab to the right is # selected, most likely due to determination of mouse position @@ -11,7 +11,7 @@ # tab index?). This will also help with finding close buttons. # ToDo: Fix page preview code (PFNotebookPagePreview) # -#= ============================================================================== +# =============================================================================== import wx import wx.lib.newevent @@ -413,7 +413,7 @@ class _TabRenderer: mdc.SelectObject(ebmp) mdc.SetFont(self.font) textSizeX, textSizeY = mdc.GetTextExtent(self.text) - totalSize = self.left_width + self.right_width + textSizeX + self.close_btn_width / 2 + 16 + self.padding* 2 + totalSize = self.left_width + self.right_width + textSizeX + self.close_btn_width / 2 + 16 + self.padding * 2 mdc.SelectObject(wx.NullBitmap) return totalSize, self.tab_height @@ -1478,4 +1478,3 @@ if __name__ == "__main__": top = Frame("Test Chrome Tabs") top.Show() app.MainLoop() - diff --git a/gui/esiFittings.py b/gui/esiFittings.py index 98944fde1..ca04387e5 100644 --- a/gui/esiFittings.py +++ b/gui/esiFittings.py @@ -29,7 +29,6 @@ class EveFittings(wx.Frame): self.mainFrame = parent mainSizer = wx.BoxSizer(wx.VERTICAL) - sEsi = Esi.getInstance() characterSelectSizer = wx.BoxSizer(wx.HORIZONTAL) @@ -119,10 +118,11 @@ class EveFittings(wx.Frame): pyfalog.error(msg) self.statusbar.SetStatusText(msg) except APIException as ex: - del waitDialog # Can't do this in a finally because then it obscures the message dialog + # Can't do this in a finally because then it obscures the message dialog + del waitDialog # noqa: F821 ESIExceptionHandler(self, ex) except Exception as ex: - del waitDialog + del waitDialog # noqa: F821 raise ex def importFitting(self, event): @@ -180,7 +180,6 @@ class ExportToEve(wx.Frame): self.mainFrame = parent self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) - sEsi = Esi.getInstance() mainSizer = wx.BoxSizer(wx.VERTICAL) hSizer = wx.BoxSizer(wx.HORIZONTAL) @@ -232,7 +231,6 @@ 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) @@ -242,12 +240,8 @@ 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) @@ -307,7 +301,7 @@ class SsoCharacterMgmt(wx.Dialog): def ssoLogin(self, event): if (self): - #todo: these events don't unbind properly when window is closed (?), hence the `if`. Figure out better way of doing this. + # todo: these events don't unbind properly when window is closed (?), hence the `if`. Figure out better way of doing this. self.popCharList() event.Skip() @@ -372,6 +366,9 @@ class FittingsTreeView(wx.Panel): if (fit['fitting_id'] in sEsi.fittings_deleted): continue ship = getItem(fit['ship_type_id']) + if ship is None: + pyfalog.debug('Cannot find ship type id: {}'.format(fit['ship_type_id'])) + continue if ship.name not in dict: dict[ship.name] = [] dict[ship.name].append(fit) diff --git a/gui/ssoLogin.py b/gui/ssoLogin.py index 2ff364752..4a8f1197b 100644 --- a/gui/ssoLogin.py +++ b/gui/ssoLogin.py @@ -1,5 +1,6 @@ import wx + class SsoLogin(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, id=wx.ID_ANY, title="SSO Login", size=wx.Size(400, 240)) diff --git a/gui/updateDialog.py b/gui/updateDialog.py index c575eeaf3..c596d553e 100644 --- a/gui/updateDialog.py +++ b/gui/updateDialog.py @@ -62,7 +62,6 @@ class UpdateDialog(wx.Dialog): self.browser.Bind(wx.html2.EVT_WEBVIEW_NEWWINDOW, self.OnNewWindow) link_patterns = [ - (re.compile("([0-9a-f]{6,40})", re.I), r"https://github.com/pyfa-org/Pyfa/commit/\1"), (re.compile("#(\d+)", re.I), r"https://github.com/pyfa-org/Pyfa/issues/\1"), (re.compile("@(\w+)", re.I), r"https://github.com/\1") ] @@ -71,12 +70,27 @@ class UpdateDialog(wx.Dialog): extras=['cuddled-lists', 'fenced-code-blocks', 'target-blank-links', 'toc', 'link-patterns'], link_patterns=link_patterns) + release_markup = markdowner.convert(self.releaseInfo['body']) + + # run the text through markup again, this time with the hashing pattern. This is required due to bugs in markdown2: + # https://github.com/trentm/python-markdown2/issues/287 + link_patterns = [ + (re.compile("([0-9a-f]{6,40})", re.I), r"https://github.com/pyfa-org/Pyfa/commit/\1"), + ] + + markdowner = markdown2.Markdown( + extras=['cuddled-lists', 'fenced-code-blocks', 'target-blank-links', 'toc', 'link-patterns'], + link_patterns=link_patterns) + + # The space here is required, again, due to bug. Again, see https://github.com/trentm/python-markdown2/issues/287 + release_markup = markdowner.convert(' ' + release_markup) + self.browser.SetPage(html_tmpl.format( self.releaseInfo['tag_name'], releaseDate.strftime('%B %d, %Y'), "

This is a pre-release, be prepared for unstable features

" if version.is_prerelease else "", - markdowner.convert(self.releaseInfo['body']) - ),"") + release_markup + ), "") notesSizer.Add(self.browser, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5) mainSizer.Add(notesSizer, 1, wx.EXPAND, 5) diff --git a/gui/utils/exportHtml.py b/gui/utils/exportHtml.py index 612df367e..0d5456dd0 100644 --- a/gui/utils/exportHtml.py +++ b/gui/utils/exportHtml.py @@ -86,7 +86,7 @@ class exportHtmlThread(threading.Thread): Pyfa Fittings - +