diff --git a/eos/__init__.py b/eos/__init__.py index f6e146b5f..96a3c75be 100644 --- a/eos/__init__.py +++ b/eos/__init__.py @@ -1,8 +1,8 @@ -version = "0.2.3" -tag = "git" - - -def test(): - import tests.runTests - import unittest - unittest.main(defaultTest="discover", testLoader=tests.runTests.loader) +version = "0.2.3" +tag = "git" + + +def test(): + import tests.runTests + import unittest + unittest.main(defaultTest="discover", testLoader=tests.runTests.loader) diff --git a/eos/db/gamedata/metaData.py b/eos/db/gamedata/metaData.py index 6bf500a72..bb23e9315 100644 --- a/eos/db/gamedata/metaData.py +++ b/eos/db/gamedata/metaData.py @@ -1,30 +1,30 @@ -# =============================================================================== -# Copyright (C) 2010 Diego Duclos -# -# This file is part of eos. -# -# eos is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# eos 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with eos. If not, see . -# =============================================================================== - -from sqlalchemy import Column, Table, String -from sqlalchemy.orm import mapper - -from eos.db import gamedata_meta -from eos.types import MetaData - -metadata_table = Table("metadata", gamedata_meta, - Column("field_name", String, primary_key=True), - Column("field_value", String)) - -mapper(MetaData, metadata_table) +# =============================================================================== +# Copyright (C) 2010 Diego Duclos +# +# This file is part of eos. +# +# eos is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# eos 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with eos. If not, see . +# =============================================================================== + +from sqlalchemy import Column, Table, String +from sqlalchemy.orm import mapper + +from eos.db import gamedata_meta +from eos.types import MetaData + +metadata_table = Table("metadata", gamedata_meta, + Column("field_name", String, primary_key=True), + Column("field_value", String)) + +mapper(MetaData, metadata_table) diff --git a/eos/effects/modifyactivearmorresonancepostpercent.py b/eos/effects/modifyactivearmorresonancepostpercent.py index be8b613a8..6a6a9e571 100644 --- a/eos/effects/modifyactivearmorresonancepostpercent.py +++ b/eos/effects/modifyactivearmorresonancepostpercent.py @@ -1,13 +1,13 @@ -# modifyActiveArmorResonancePostPercent -# -# Used by: -# Modules from group: Armor Hardener (156 of 156) -# Modules from group: Flex Armor Hardener (4 of 4) -type = "active" - - -def handler(fit, module, context): - for damageType in ("kinetic", "thermal", "explosive", "em"): - fit.ship.boostItemAttr("armor%sDamageResonance" % damageType.capitalize(), - module.getModifiedItemAttr("%sDamageResistanceBonus" % damageType), - stackingPenalties=True) +# modifyActiveArmorResonancePostPercent +# +# Used by: +# Modules from group: Armor Hardener (156 of 156) +# Modules from group: Flex Armor Hardener (4 of 4) +type = "active" + + +def handler(fit, module, context): + for damageType in ("kinetic", "thermal", "explosive", "em"): + fit.ship.boostItemAttr("armor%sDamageResonance" % damageType.capitalize(), + module.getModifiedItemAttr("%sDamageResistanceBonus" % damageType), + stackingPenalties=True) diff --git a/eos/effects/modifyactiveshieldresonancepostpercent.py b/eos/effects/modifyactiveshieldresonancepostpercent.py index 41e70a776..04c2edac3 100644 --- a/eos/effects/modifyactiveshieldresonancepostpercent.py +++ b/eos/effects/modifyactiveshieldresonancepostpercent.py @@ -1,13 +1,13 @@ -# modifyActiveShieldResonancePostPercent -# -# Used by: -# Modules from group: Flex Shield Hardener (5 of 5) -# Modules from group: Shield Hardener (97 of 97) -type = "active" - - -def handler(fit, module, context): - for damageType in ("kinetic", "thermal", "explosive", "em"): - fit.ship.boostItemAttr("shield" + damageType.capitalize() + "DamageResonance", - module.getModifiedItemAttr(damageType + "DamageResistanceBonus"), - stackingPenalties=True) +# modifyActiveShieldResonancePostPercent +# +# Used by: +# Modules from group: Flex Shield Hardener (5 of 5) +# Modules from group: Shield Hardener (97 of 97) +type = "active" + + +def handler(fit, module, context): + for damageType in ("kinetic", "thermal", "explosive", "em"): + fit.ship.boostItemAttr("shield" + damageType.capitalize() + "DamageResonance", + module.getModifiedItemAttr(damageType + "DamageResistanceBonus"), + stackingPenalties=True) diff --git a/eos/effects/shipbonusrepairsystemsbonusatc2.py b/eos/effects/shipbonusrepairsystemsbonusatc2.py index b2f7bd1aa..c761ad921 100644 --- a/eos/effects/shipbonusrepairsystemsbonusatc2.py +++ b/eos/effects/shipbonusrepairsystemsbonusatc2.py @@ -1,10 +1,10 @@ -# shipBonusRepairSystemsBonusATC2 -# -# Used by: -# Ship: Vangel -type = "passive" - - -def handler(fit, ship, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), - "armorDamageAmount", ship.getModifiedItemAttr("shipBonusATC2")) +# shipBonusRepairSystemsBonusATC2 +# +# Used by: +# Ship: Vangel +type = "passive" + + +def handler(fit, ship, context): + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), + "armorDamageAmount", ship.getModifiedItemAttr("shipBonusATC2")) diff --git a/eos/effects/shipenergyneutralizertransferamountbonusab.py b/eos/effects/shipenergyneutralizertransferamountbonusab.py index c814b51b5..925a33c92 100644 --- a/eos/effects/shipenergyneutralizertransferamountbonusab.py +++ b/eos/effects/shipenergyneutralizertransferamountbonusab.py @@ -1,11 +1,11 @@ -# shipEnergyNeutralizerTransferAmountBonusAB -# -# Used by: -# Ship: Bhaalgorn -type = "passive" - - -def handler(fit, ship, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Energy Neutralizer", - "energyNeutralizerAmount", ship.getModifiedItemAttr("shipBonusAB"), - skill="Amarr Battleship") +# shipEnergyNeutralizerTransferAmountBonusAB +# +# Used by: +# Ship: Bhaalgorn +type = "passive" + + +def handler(fit, ship, context): + fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Energy Neutralizer", + "energyNeutralizerAmount", ship.getModifiedItemAttr("shipBonusAB"), + skill="Amarr Battleship") diff --git a/eos/effects/skillreactivearmorhardenercapneedbonus.py b/eos/effects/skillreactivearmorhardenercapneedbonus.py index 22b9f94c4..a8baab0f4 100644 --- a/eos/effects/skillreactivearmorhardenercapneedbonus.py +++ b/eos/effects/skillreactivearmorhardenercapneedbonus.py @@ -1,13 +1,13 @@ -# skillReactiveArmorHardenerCapNeedBonus -# -# Used by: -# Skill: Resistance Phasing -type = "passive" - - -def handler(fit, src, context): - lvl = src.level - fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Resistance Shift Hardener", "capacitorNeed", - src.getModifiedItemAttr("capNeedBonus") * lvl) - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Resistance Phasing"), "capacitorNeed", - src.getModifiedItemAttr("capNeedBonus") * lvl) +# skillReactiveArmorHardenerCapNeedBonus +# +# Used by: +# Skill: Resistance Phasing +type = "passive" + + +def handler(fit, src, context): + lvl = src.level + fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Resistance Shift Hardener", "capacitorNeed", + src.getModifiedItemAttr("capNeedBonus") * lvl) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Resistance Phasing"), "capacitorNeed", + src.getModifiedItemAttr("capNeedBonus") * lvl) diff --git a/eos/effects/skillreactivearmorhardenerdurationbonus.py b/eos/effects/skillreactivearmorhardenerdurationbonus.py index 9ecabd1ca..00ced0d4f 100644 --- a/eos/effects/skillreactivearmorhardenerdurationbonus.py +++ b/eos/effects/skillreactivearmorhardenerdurationbonus.py @@ -1,13 +1,13 @@ -# skillReactiveArmorHardenerDurationBonus -# -# Used by: -# Skill: Resistance Phasing -type = "passive" - - -def handler(fit, src, context): - lvl = src.level - fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Resistance Shift Hardener", "duration", - src.getModifiedItemAttr("durationBonus") * lvl) - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Resistance Phasing"), "duration", - src.getModifiedItemAttr("durationBonus") * lvl) +# skillReactiveArmorHardenerDurationBonus +# +# Used by: +# Skill: Resistance Phasing +type = "passive" + + +def handler(fit, src, context): + lvl = src.level + fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Armor Resistance Shift Hardener", "duration", + src.getModifiedItemAttr("durationBonus") * lvl) + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Resistance Phasing"), "duration", + src.getModifiedItemAttr("durationBonus") * lvl) diff --git a/eos/effects/subsystembonusamarrdefensivearmorrepairamount.py b/eos/effects/subsystembonusamarrdefensivearmorrepairamount.py index 27bb5924b..4928f9906 100644 --- a/eos/effects/subsystembonusamarrdefensivearmorrepairamount.py +++ b/eos/effects/subsystembonusamarrdefensivearmorrepairamount.py @@ -1,11 +1,11 @@ -# subsystemBonusAmarrDefensiveArmorRepairAmount -# -# Used by: -# Subsystem: Legion Defensive - Nanobot Injector -type = "passive" - - -def handler(fit, module, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), - "armorDamageAmount", module.getModifiedItemAttr("subsystemBonusAmarrDefensive"), - skill="Amarr Defensive Systems") +# subsystemBonusAmarrDefensiveArmorRepairAmount +# +# Used by: +# Subsystem: Legion Defensive - Nanobot Injector +type = "passive" + + +def handler(fit, module, context): + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), + "armorDamageAmount", module.getModifiedItemAttr("subsystemBonusAmarrDefensive"), + skill="Amarr Defensive Systems") diff --git a/eos/effects/subsystembonusgallentedefensivearmorrepairamount.py b/eos/effects/subsystembonusgallentedefensivearmorrepairamount.py index 5b17e2461..32dc79789 100644 --- a/eos/effects/subsystembonusgallentedefensivearmorrepairamount.py +++ b/eos/effects/subsystembonusgallentedefensivearmorrepairamount.py @@ -1,11 +1,11 @@ -# subsystemBonusGallenteDefensiveArmorRepairAmount -# -# Used by: -# Subsystem: Proteus Defensive - Nanobot Injector -type = "passive" - - -def handler(fit, module, context): - fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), - "armorDamageAmount", module.getModifiedItemAttr("subsystemBonusGallenteDefensive"), - skill="Gallente Defensive Systems") +# subsystemBonusGallenteDefensiveArmorRepairAmount +# +# Used by: +# Subsystem: Proteus Defensive - Nanobot Injector +type = "passive" + + +def handler(fit, module, context): + fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems"), + "armorDamageAmount", module.getModifiedItemAttr("subsystemBonusGallenteDefensive"), + skill="Gallente Defensive Systems") diff --git a/eos/enum.py b/eos/enum.py index e9fb20a0b..04caea536 100644 --- a/eos/enum.py +++ b/eos/enum.py @@ -1,23 +1,23 @@ -class Enum(): - def __init__(self): - pass - - @classmethod - def getTypes(cls): - for stuff in cls.__dict__: - if stuff.upper() == stuff: - yield stuff - - @classmethod - def getName(cls, v): - map = getattr(cls, "_map", None) - if map is None: - map = cls._map = {} - for type in cls.getTypes(): - map[cls.getValue(type)] = type - - return map.get(v) - - @classmethod - def getValue(cls, type): - return cls.__dict__[type] +class Enum(): + def __init__(self): + pass + + @classmethod + def getTypes(cls): + for stuff in cls.__dict__: + if stuff.upper() == stuff: + yield stuff + + @classmethod + def getName(cls, v): + map = getattr(cls, "_map", None) + if map is None: + map = cls._map = {} + for type in cls.getTypes(): + map[cls.getValue(type)] = type + + return map.get(v) + + @classmethod + def getValue(cls, type): + return cls.__dict__[type] diff --git a/eos/eqBase.py b/eos/eqBase.py index a400aec33..2b8d35b33 100644 --- a/eos/eqBase.py +++ b/eos/eqBase.py @@ -1,29 +1,29 @@ -# =============================================================================== -# Copyright (C) 2010 Diego Duclos -# -# This file is part of eos. -# -# eos is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# eos 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with eos. If not, see . -# =============================================================================== - - -class EqBase(object): - def __eq__(self, other): - return type(self) == type(other) and self.ID == other.ID - - def __ne__(self, other): - return type(self) != type(other) or self.ID != other.ID - - def __hash__(self): - return id(type(self)) + self.ID +# =============================================================================== +# Copyright (C) 2010 Diego Duclos +# +# This file is part of eos. +# +# eos is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# eos 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with eos. If not, see . +# =============================================================================== + + +class EqBase(object): + def __eq__(self, other): + return type(self) == type(other) and self.ID == other.ID + + def __ne__(self, other): + return type(self) != type(other) or self.ID != other.ID + + def __hash__(self): + return id(type(self)) + self.ID diff --git a/eos/graph/__init__.py b/eos/graph/__init__.py index 882ac35d1..44f6905c7 100644 --- a/eos/graph/__init__.py +++ b/eos/graph/__init__.py @@ -1,118 +1,118 @@ -# =============================================================================== -# Copyright (C) 2010 Diego Duclos -# -# This file is part of eos. -# -# eos is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# eos 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with eos. If not, see . -# =============================================================================== - -import itertools - - -class Graph(object): - def __init__(self, fit, function, data=None): - self.fit = fit - self.data = {} - if data is not None: - for name, d in data.iteritems(): - self.setData(Data(name, d)) - - self.function = function - - def clearData(self): - self.data.clear() - - def setData(self, data): - self.data[data.name] = data - - def getIterator(self): - pointNames = [] - pointIterators = [] - for data in self.data.itervalues(): - pointNames.append(data.name) - pointIterators.append(data) - - return self._iterator(pointNames, pointIterators) - - def _iterator(self, pointNames, pointIterators): - for pointValues in itertools.product(*pointIterators): - point = {} - for i in xrange(len(pointValues)): - point[pointNames[i]] = pointValues[i] - - yield point, self.function(point) - - -class Data(object): - def __init__(self, name, dataString, step=None): - self.name = name - self.step = step - self.data = self.parseString(dataString) - - def parseString(self, dataString): - if not isinstance(dataString, basestring): - return (Constant(dataString),) - - dataList = [] - for data in dataString.split(";"): - if isinstance(data, basestring) and "-" in data: - # Dealing with a range - dataList.append(Range(data, self.step)) - else: - dataList.append(Constant(data)) - - return dataList - - def __iter__(self): - for data in self.data: - for value in data: - yield value - - def isConstant(self): - return len(self.data) == 1 and self.data[0].isConstant() - - -class Constant(object): - def __init__(self, const): - if isinstance(const, basestring): - self.value = None if const == "" else float(const) - else: - self.value = const - - def __iter__(self): - yield self.value - - def isConstant(self): - return True - - -class Range(object): - def __init__(self, string, step): - start, end = string.split("-") - self.start = float(start) - self.end = float(end) - self.step = step - - def __iter__(self): - current = start = self.start - end = self.end - step = self.step or (end - start) / 50.0 - i = 1 - while current < end: - current = start + i * step - i += 1 - yield current - - def isConstant(self): - return False +# =============================================================================== +# Copyright (C) 2010 Diego Duclos +# +# This file is part of eos. +# +# eos is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# eos 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with eos. If not, see . +# =============================================================================== + +import itertools + + +class Graph(object): + def __init__(self, fit, function, data=None): + self.fit = fit + self.data = {} + if data is not None: + for name, d in data.iteritems(): + self.setData(Data(name, d)) + + self.function = function + + def clearData(self): + self.data.clear() + + def setData(self, data): + self.data[data.name] = data + + def getIterator(self): + pointNames = [] + pointIterators = [] + for data in self.data.itervalues(): + pointNames.append(data.name) + pointIterators.append(data) + + return self._iterator(pointNames, pointIterators) + + def _iterator(self, pointNames, pointIterators): + for pointValues in itertools.product(*pointIterators): + point = {} + for i in xrange(len(pointValues)): + point[pointNames[i]] = pointValues[i] + + yield point, self.function(point) + + +class Data(object): + def __init__(self, name, dataString, step=None): + self.name = name + self.step = step + self.data = self.parseString(dataString) + + def parseString(self, dataString): + if not isinstance(dataString, basestring): + return (Constant(dataString),) + + dataList = [] + for data in dataString.split(";"): + if isinstance(data, basestring) and "-" in data: + # Dealing with a range + dataList.append(Range(data, self.step)) + else: + dataList.append(Constant(data)) + + return dataList + + def __iter__(self): + for data in self.data: + for value in data: + yield value + + def isConstant(self): + return len(self.data) == 1 and self.data[0].isConstant() + + +class Constant(object): + def __init__(self, const): + if isinstance(const, basestring): + self.value = None if const == "" else float(const) + else: + self.value = const + + def __iter__(self): + yield self.value + + def isConstant(self): + return True + + +class Range(object): + def __init__(self, string, step): + start, end = string.split("-") + self.start = float(start) + self.end = float(end) + self.step = step + + def __iter__(self): + current = start = self.start + end = self.end + step = self.step or (end - start) / 50.0 + i = 1 + while current < end: + current = start + i * step + i += 1 + yield current + + def isConstant(self): + return False diff --git a/gui/builtinContextMenus/metaSwap.py b/gui/builtinContextMenus/metaSwap.py index 3462410e5..245f864d7 100644 Binary files a/gui/builtinContextMenus/metaSwap.py and b/gui/builtinContextMenus/metaSwap.py differ diff --git a/gui/builtinContextMenus/moduleAmmoPicker.py b/gui/builtinContextMenus/moduleAmmoPicker.py index e69aac4cd..f130c2130 100644 Binary files a/gui/builtinContextMenus/moduleAmmoPicker.py and b/gui/builtinContextMenus/moduleAmmoPicker.py differ diff --git a/gui/builtinGraphs/__init__.py b/gui/builtinGraphs/__init__.py index ec25b90b2..31eaaaf9e 100644 --- a/gui/builtinGraphs/__init__.py +++ b/gui/builtinGraphs/__init__.py @@ -1 +1 @@ -__all__ = ["fitDps"] +__all__ = ["fitDps"] diff --git a/gui/builtinViewColumns/__init__.py b/gui/builtinViewColumns/__init__.py index d66f423bf..cff8bc614 100644 --- a/gui/builtinViewColumns/__init__.py +++ b/gui/builtinViewColumns/__init__.py @@ -1,2 +1,2 @@ -__all__ = ["ammo", "ammoIcon", "attributeDisplay", "baseIcon", "baseName", - "capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities"] +__all__ = ["ammo", "ammoIcon", "attributeDisplay", "baseIcon", "baseName", + "capacitorUse", "maxRange", "price", "propertyDisplay", "state", "misc", "abilities"] diff --git a/gui/builtinViewColumns/baseName.py b/gui/builtinViewColumns/baseName.py index 973219b2c..ef68015f8 100644 Binary files a/gui/builtinViewColumns/baseName.py and b/gui/builtinViewColumns/baseName.py differ diff --git a/gui/graphFrame.py b/gui/graphFrame.py index 9b6520a5f..7b56c0ed0 100644 --- a/gui/graphFrame.py +++ b/gui/graphFrame.py @@ -19,6 +19,7 @@ import os import logging +import imp import wx @@ -30,15 +31,15 @@ from gui.graph import Graph from gui.bitmapLoader import BitmapLoader from config import parsePath +# Don't actually import the thing, since it takes for fucking ever try: - import matplotlib as mpl - from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas - from matplotlib.figure import Figure + imp.find_module('matplotlib') enabled = True - mplImported = False except ImportError: enabled = False +mplImported = False + logger = logging.getLogger(__name__) if not enabled: logger.info("Problems importing matplotlib; continuing without graphs") @@ -50,6 +51,15 @@ class GraphFrame(wx.Frame): global enabled global mplImported + # Import here + try: + import matplotlib as mpl + from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas + from matplotlib.figure import Figure + enabled = True + except ImportError: + enabled = False + self.legendFix = False if not enabled: return diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 244ac215b..e33c8bac9 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -146,6 +146,8 @@ class MainFrame(wx.Frame): # Load stored settings (width/height/maximized..) self.LoadMainFrameAttribs() + self.disableOverrideEditor = disableOverrideEditor + # Fix for msw (have the frame background color match panel color if 'wxMSW' in wx.PlatformInfo: self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) @@ -205,7 +207,7 @@ class MainFrame(wx.Frame): self.closePageId = wx.NewId() self.widgetInspectMenuID = wx.NewId() - self.SetMenuBar(MainMenuBar()) + self.SetMenuBar(MainMenuBar(self)) self.registerMenu() # Internal vars to keep track of other windows (graphing/stats) diff --git a/gui/mainMenuBar.py b/gui/mainMenuBar.py index b543998c2..5e28da949 100644 --- a/gui/mainMenuBar.py +++ b/gui/mainMenuBar.py @@ -21,8 +21,7 @@ import wx import config from service.character import Character -import gui.mainFrame -import gui.graphFrame +#import gui.graphFrame import gui.globalEvents as GE from gui.bitmapLoader import BitmapLoader @@ -32,7 +31,7 @@ if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION class MainMenuBar(wx.MenuBar): - def __init__(self): + def __init__(self, mainFrame): self.characterEditorId = wx.NewId() self.damagePatternEditorId = wx.NewId() self.targetResistsEditorId = wx.NewId() @@ -58,7 +57,7 @@ class MainMenuBar(wx.MenuBar): wx.ID_COPY = wx.NewId() wx.ID_PASTE = wx.NewId() - self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.mainFrame = mainFrame wx.MenuBar.__init__(self) # File menu @@ -139,7 +138,7 @@ class MainMenuBar(wx.MenuBar): self.Enable(self.eveFittingsId, False) self.Enable(self.exportToEveId, False) - if not gui.mainFrame.disableOverrideEditor: + if not self.mainFrame.disableOverrideEditor: windowMenu.AppendSeparator() attrItem = wx.MenuItem(windowMenu, self.attrEditorId, "Attribute Overrides\tCTRL+B") attrItem.SetBitmap(BitmapLoader.getBitmap("fit_rename_small", "gui")) diff --git a/scripts/dist.py b/scripts/dist.py index 3d6f7c3af..588418a39 100755 --- a/scripts/dist.py +++ b/scripts/dist.py @@ -1,257 +1,257 @@ -#!/usr/bin/env python -""" -Script for generating distributables based on platform skeletons. - -User supplies path for pyfa code base, root skeleton directory, and where the -builds go. The builds are automatically named depending on the pyfa config -values of `version` and `tag`. If it's a Stable release, the naming -convention is: - - pyfa-pyfaversion-expansion-expversion-platform - -If it is not Stable (tag=git), we determine if the pyfa code base includes -the git repo to use as an ID. If not, uses randomly generated 6-character ID. -The unstable naming convention: - - pyfa-YYYMMDD-id-platform - -dist.py can also build the Windows installer provided that it has a path to -Inno Setup (and, for generating on non-Windows platforms, that WINE is -installed). To build the EXE file, `win` must be included in the platforms to -be built. -""" - -#@todo: ensure build directory can be written to -# todo: default build and dist directories - -from optparse import OptionParser -import os.path -import shutil -import sys -import tarfile -import datetime -import random -import string -import zipfile -import errno -from subprocess import call - -class FileStub(): - def write(self, *args): - pass - - def flush(self, *args): - pass - -i = 0 -def loginfo(path, names): - # Print out a "progress" and return directories / files to ignore - global i - i += 1 - if i % 10 == 0: - sys.stdout.write(".") - sys.stdout.flush() - return () - -def copyanything(src, dst): - try: - shutil.copytree(src, dst, ignore=loginfo) - except: # python >2.5 - try: - shutil.copy(src, dst) - except: - raise - -def id_generator(size=6, chars=string.ascii_uppercase + string.digits): - return ''.join(random.choice(chars) for x in range(size)) - -def zipdir(path, zip): - for root, dirs, files in os.walk(path): - for file in files: - zip.write(os.path.join(root, file)) - -skels = ['win', 'src', 'mac', 'mac-deprecated'] -iscc = "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" # inno script location via wine - -if __name__ == "__main__": - oldstd = sys.stdout - parser = OptionParser() - parser.add_option("-s", "--skeleton", dest="skeleton", help="Location of Pyfa-skel directory") - parser.add_option("-b", "--base", dest="base", help="Location of cleaned read-only base directory") - parser.add_option("-d", "--destination", dest="destination", help="Where to copy our distributable") - parser.add_option("-p", "--platforms", dest="platforms", help="Comma-separated list of platforms to build", default=','.join(skels)) - parser.add_option("-q", "--quiet", dest="silent", action="store_true") - parser.add_option("-w", "--winexe", dest="winexe", action="store_true", help="Build the Windows installer file (needs Inno Setup). Must include 'win' in platform options") - parser.add_option("-z", "--zip", dest="zip", action="store_true", help="zip archive instead of tar") - - options, args = parser.parse_args() - - if options.skeleton is None or options.base is None or options.destination is None: - print "Need --skeleton argument as well as --base and --destination argument" - parser.print_help() - sys.exit() - - if options.silent: - sys.stdout = FileStub() - - options.platforms = options.platforms.split(",") - - for skel in skels: - if skel not in options.platforms: - continue - - print "\n======== %s ========"%skel - - info = {} - config = {} - setup = {} - skeleton = os.path.expanduser(os.path.join(options.skeleton, skel)) - - execfile(os.path.join(options.base, "config.py"), config) - execfile(os.path.join(skeleton, "info.py"), info) - execfile(os.path.join(options.base, "setup.py"), setup) - - destination = os.path.expanduser(options.destination) - if not os.path.isdir(destination) or not os.access(destination, os.W_OK | os.X_OK): - print "Destination directory does not exist or is not writable: {}".format(destination) - sys.exit() - - dirName = info["arcname"] - - nowdt = datetime.datetime.now() - now = "%04d%02d%02d" % (nowdt.year, nowdt.month, nowdt.day) - - git = False - if config['tag'].lower() == "git": - try: # if there is a git repo associated with base, use master commit - with open(os.path.join(options.base, ".git", "refs", "heads", "master"), 'r') as f: - id = f.readline()[0:6] - git = True - except: # else, use custom ID - id = id_generator() - fileName = "pyfa-{}-{}-{}".format(now, id, info["os"]) - else: - fileName = "pyfa-{}-{}-{}-{}".format( - config['version'], - config['expansionName'].lower(), - config['expansionVersion'], - info["os"] - ) - - archiveName = "{}.{}".format(fileName, "zip" if options.zip else "tar.bz2") - tmpDir = os.path.join(os.getcwd(), dirName) # tmp directory where files are copied - tmpFile = os.path.join(os.getcwd(), archiveName) - - try: - print "Copying skeleton to ", tmpDir - shutil.copytree(skeleton, tmpDir, ignore=loginfo) - print - source = os.path.expanduser(options.base) - root = os.path.join(tmpDir, info["base"]) - - # it is easier to work from the source directory - oldcwd = os.getcwd() - os.chdir(source) - - if info["library"]: - print "Injecting files into", info["library"] - libraryFile = os.path.join(root, info["library"]) - - with zipfile.ZipFile(libraryFile, 'a') as library: - for dir in setup['packages']: - zipdir(dir, library) - library.write('pyfa.py', 'pyfa__main__.py') - library.write('config.py') - else: # platforms where we don't have a packaged library - print "Copying modules into", root - for dir in setup['packages']: - copyanything(dir, os.path.join(root, dir)) - - # add some additional files to root dir for these platforms - # (hopefully can figure out a way later for OS X to use the one in - # it's library) - if skel == 'mac': - setup['include_files'] += ['pyfa.py'] - if skel in ('src', 'mac-deprecated'): - setup['include_files'] += ['pyfa.py', 'config.py'] - - print - print "Copying included files:", - - for file in setup['include_files']: - if isinstance(file, basestring): - print file, - copyanything(file, os.path.join(root, file)) - - print - print "Creating images zipfile:", - os.chdir('imgs') - imagesFile = os.path.join(root, "imgs.zip") - - with zipfile.ZipFile(imagesFile, 'w') as images: - for dir in setup['icon_dirs']: - print dir, - zipdir(dir, images) - os.chdir(oldcwd) - - print - print "Creating archive" - if options.zip: - archive = zipfile.ZipFile(tmpFile, 'w', compression=zipfile.ZIP_DEFLATED) - zipdir(dirName, archive) - archive.close() - else: - archive = tarfile.open(tmpFile, "w:bz2") - archive.add(tmpDir, arcname=info["arcname"]) - archive.close() - - print "Moving archive to ", destination - shutil.move(tmpFile, destination) - - if "win" in skel and options.winexe: - print "Compiling EXE" - - if config['tag'].lower() == "git": - if git: # if git repo info available, use git commit - expansion = "git-%s"%(id) - else: # if there is no git repo, use timestamp - expansion = now - else: # if code is Stable, use expansion name - expansion = "%s %s"%(config['expansionName'], config['expansionVersion']), - - calllist = ["wine"] if 'win' not in sys.platform else [] - - call(calllist + [ - iscc, - "pyfa-setup.iss", - "/dMyAppVersion=%s"%(config['version']), - "/dMyAppExpansion=%s"%(expansion), - "/dMyAppDir=pyfa", - "/dMyOutputDir=%s"%destination, - "/dMyOutputFile=%s"%fileName]) #stdout=devnull, stderr=devnull - - print "EXE completed" - - except Exception as e: - print "Encountered an error: \n\t", e - raise - finally: - print "Deleting tmp files\n" - try: - shutil.rmtree("dist") # Inno dir - except: - pass - try: - shutil.rmtree(tmpDir) - except: - pass - try: - os.unlink(tmpFile) - except: - pass - - sys.stdout = oldstd - if os.path.isdir(destination): - print os.path.join(destination, os.path.split(tmpFile)[1]) - else: - print destination +#!/usr/bin/env python +""" +Script for generating distributables based on platform skeletons. + +User supplies path for pyfa code base, root skeleton directory, and where the +builds go. The builds are automatically named depending on the pyfa config +values of `version` and `tag`. If it's a Stable release, the naming +convention is: + + pyfa-pyfaversion-expansion-expversion-platform + +If it is not Stable (tag=git), we determine if the pyfa code base includes +the git repo to use as an ID. If not, uses randomly generated 6-character ID. +The unstable naming convention: + + pyfa-YYYMMDD-id-platform + +dist.py can also build the Windows installer provided that it has a path to +Inno Setup (and, for generating on non-Windows platforms, that WINE is +installed). To build the EXE file, `win` must be included in the platforms to +be built. +""" + +#@todo: ensure build directory can be written to +# todo: default build and dist directories + +from optparse import OptionParser +import os.path +import shutil +import sys +import tarfile +import datetime +import random +import string +import zipfile +import errno +from subprocess import call + +class FileStub(): + def write(self, *args): + pass + + def flush(self, *args): + pass + +i = 0 +def loginfo(path, names): + # Print out a "progress" and return directories / files to ignore + global i + i += 1 + if i % 10 == 0: + sys.stdout.write(".") + sys.stdout.flush() + return () + +def copyanything(src, dst): + try: + shutil.copytree(src, dst, ignore=loginfo) + except: # python >2.5 + try: + shutil.copy(src, dst) + except: + raise + +def id_generator(size=6, chars=string.ascii_uppercase + string.digits): + return ''.join(random.choice(chars) for x in range(size)) + +def zipdir(path, zip): + for root, dirs, files in os.walk(path): + for file in files: + zip.write(os.path.join(root, file)) + +skels = ['win', 'src', 'mac', 'mac-deprecated'] +iscc = "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" # inno script location via wine + +if __name__ == "__main__": + oldstd = sys.stdout + parser = OptionParser() + parser.add_option("-s", "--skeleton", dest="skeleton", help="Location of Pyfa-skel directory") + parser.add_option("-b", "--base", dest="base", help="Location of cleaned read-only base directory") + parser.add_option("-d", "--destination", dest="destination", help="Where to copy our distributable") + parser.add_option("-p", "--platforms", dest="platforms", help="Comma-separated list of platforms to build", default=','.join(skels)) + parser.add_option("-q", "--quiet", dest="silent", action="store_true") + parser.add_option("-w", "--winexe", dest="winexe", action="store_true", help="Build the Windows installer file (needs Inno Setup). Must include 'win' in platform options") + parser.add_option("-z", "--zip", dest="zip", action="store_true", help="zip archive instead of tar") + + options, args = parser.parse_args() + + if options.skeleton is None or options.base is None or options.destination is None: + print "Need --skeleton argument as well as --base and --destination argument" + parser.print_help() + sys.exit() + + if options.silent: + sys.stdout = FileStub() + + options.platforms = options.platforms.split(",") + + for skel in skels: + if skel not in options.platforms: + continue + + print "\n======== %s ========"%skel + + info = {} + config = {} + setup = {} + skeleton = os.path.expanduser(os.path.join(options.skeleton, skel)) + + execfile(os.path.join(options.base, "config.py"), config) + execfile(os.path.join(skeleton, "info.py"), info) + execfile(os.path.join(options.base, "setup.py"), setup) + + destination = os.path.expanduser(options.destination) + if not os.path.isdir(destination) or not os.access(destination, os.W_OK | os.X_OK): + print "Destination directory does not exist or is not writable: {}".format(destination) + sys.exit() + + dirName = info["arcname"] + + nowdt = datetime.datetime.now() + now = "%04d%02d%02d" % (nowdt.year, nowdt.month, nowdt.day) + + git = False + if config['tag'].lower() == "git": + try: # if there is a git repo associated with base, use master commit + with open(os.path.join(options.base, ".git", "refs", "heads", "master"), 'r') as f: + id = f.readline()[0:6] + git = True + except: # else, use custom ID + id = id_generator() + fileName = "pyfa-{}-{}-{}".format(now, id, info["os"]) + else: + fileName = "pyfa-{}-{}-{}-{}".format( + config['version'], + config['expansionName'].lower(), + config['expansionVersion'], + info["os"] + ) + + archiveName = "{}.{}".format(fileName, "zip" if options.zip else "tar.bz2") + tmpDir = os.path.join(os.getcwd(), dirName) # tmp directory where files are copied + tmpFile = os.path.join(os.getcwd(), archiveName) + + try: + print "Copying skeleton to ", tmpDir + shutil.copytree(skeleton, tmpDir, ignore=loginfo) + print + source = os.path.expanduser(options.base) + root = os.path.join(tmpDir, info["base"]) + + # it is easier to work from the source directory + oldcwd = os.getcwd() + os.chdir(source) + + if info["library"]: + print "Injecting files into", info["library"] + libraryFile = os.path.join(root, info["library"]) + + with zipfile.ZipFile(libraryFile, 'a') as library: + for dir in setup['packages']: + zipdir(dir, library) + library.write('pyfa.py', 'pyfa__main__.py') + library.write('config.py') + else: # platforms where we don't have a packaged library + print "Copying modules into", root + for dir in setup['packages']: + copyanything(dir, os.path.join(root, dir)) + + # add some additional files to root dir for these platforms + # (hopefully can figure out a way later for OS X to use the one in + # it's library) + if skel == 'mac': + setup['include_files'] += ['pyfa.py'] + if skel in ('src', 'mac-deprecated'): + setup['include_files'] += ['pyfa.py', 'config.py'] + + print + print "Copying included files:", + + for file in setup['include_files']: + if isinstance(file, basestring): + print file, + copyanything(file, os.path.join(root, file)) + + print + print "Creating images zipfile:", + os.chdir('imgs') + imagesFile = os.path.join(root, "imgs.zip") + + with zipfile.ZipFile(imagesFile, 'w') as images: + for dir in setup['icon_dirs']: + print dir, + zipdir(dir, images) + os.chdir(oldcwd) + + print + print "Creating archive" + if options.zip: + archive = zipfile.ZipFile(tmpFile, 'w', compression=zipfile.ZIP_DEFLATED) + zipdir(dirName, archive) + archive.close() + else: + archive = tarfile.open(tmpFile, "w:bz2") + archive.add(tmpDir, arcname=info["arcname"]) + archive.close() + + print "Moving archive to ", destination + shutil.move(tmpFile, destination) + + if "win" in skel and options.winexe: + print "Compiling EXE" + + if config['tag'].lower() == "git": + if git: # if git repo info available, use git commit + expansion = "git-%s"%(id) + else: # if there is no git repo, use timestamp + expansion = now + else: # if code is Stable, use expansion name + expansion = "%s %s"%(config['expansionName'], config['expansionVersion']), + + calllist = ["wine"] if 'win' not in sys.platform else [] + + call(calllist + [ + iscc, + "pyfa-setup.iss", + "/dMyAppVersion=%s"%(config['version']), + "/dMyAppExpansion=%s"%(expansion), + "/dMyAppDir=pyfa", + "/dMyOutputDir=%s"%destination, + "/dMyOutputFile=%s"%fileName]) #stdout=devnull, stderr=devnull + + print "EXE completed" + + except Exception as e: + print "Encountered an error: \n\t", e + raise + finally: + print "Deleting tmp files\n" + try: + shutil.rmtree("dist") # Inno dir + except: + pass + try: + shutil.rmtree(tmpDir) + except: + pass + try: + os.unlink(tmpFile) + except: + pass + + sys.stdout = oldstd + if os.path.isdir(destination): + print os.path.join(destination, os.path.split(tmpFile)[1]) + else: + print destination