Merge branch 'SorryNotSorryBlitzmann' into development

This commit is contained in:
blitzman
2017-02-11 10:47:22 -05:00
157 changed files with 1115 additions and 991 deletions

View File

@@ -0,0 +1,13 @@
<code_scheme name="Pyfa">
<option name="LINE_SEPARATOR" value="&#xD;&#xA;" />
<option name="RIGHT_MARGIN" value="165" />
<Python>
<option name="NEW_LINE_AFTER_COLON" value="true" />
<option name="DICT_ALIGNMENT" value="2" />
<option name="DICT_NEW_LINE_AFTER_LEFT_BRACE" value="true" />
<option name="DICT_NEW_LINE_BEFORE_RIGHT_BRACE" value="true" />
<option name="USE_CONTINUATION_INDENT_FOR_ARGUMENTS" value="true" />
<option name="OPTIMIZE_IMPORTS_SORT_NAMES_IN_FROM_IMPORTS" value="true" />
<option name="OPTIMIZE_IMPORTS_JOIN_FROM_IMPORTS_WITH_SAME_SOURCE" value="true" />
</Python>
</code_scheme>

View File

@@ -0,0 +1,54 @@
<profile version="1.0">
<option name="myName" value="Pyfa" />
<inspection_tool class="IgnoreUnusedEntry" enabled="false" level="UNUSED ENTRY" enabled_by_default="false" />
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyBehaveInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyClassicStyleClassInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ourVersions">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="2.7" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="wxPython" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyPep8Inspection" enabled="true" level="TYPO" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="E203" />
<option value="E127" />
<option value="E128" />
<option value="E126" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="TYPO" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N802" />
<option value="N806" />
<option value="N803" />
<option value="N814" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyShadowingBuiltinsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyShadowingNamesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>

View File

@@ -1,8 +1,2 @@
version = "0.2.3"
tag = "git"
def test():
import tests.runTests
import unittest
unittest.main(defaultTest="discover", testLoader=tests.runTests.loader)

View File

@@ -20,10 +20,7 @@
import threading
from sqlalchemy import MetaData, create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import pool
from sqlalchemy.orm import sessionmaker
import migration
from eos import config
@@ -62,16 +59,22 @@ if saveddata_connectionstring is not None:
saveddata_meta = MetaData()
saveddata_meta.bind = saveddata_engine
saveddata_session = sessionmaker(bind=saveddata_engine, autoflush=False, expire_on_commit=False)()
else:
saveddata_meta = None
# Lock controlling any changes introduced to session
sd_lock = threading.Lock()
# Import all the definitions for all our database stuff
from eos.db.gamedata import *
from eos.db.saveddata import *
# noinspection PyPep8
from eos.db.gamedata import alphaClones, attribute, category, effect, group, icon, item, marketGroup, metaData, metaGroup, queries, traits, unit
# noinspection PyPep8
from eos.db.saveddata import booster, cargo, character, crest, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, loadDefaultDatabaseValues, miscData, module, override, price, queries, skill, targetResists, user
# Import queries
# noinspection PyPep8
from eos.db.gamedata.queries import *
# noinspection PyPep8
from eos.db.saveddata.queries import *
# If using in memory saveddata, you'll want to reflect it so the data structure is good.

View File

@@ -39,8 +39,8 @@ items_table = Table("invtypes", gamedata_meta,
Column("iconID", Integer, ForeignKey("icons.iconID")),
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True))
from .metaGroup import metatypes_table # noqa
from .traits import traits_table # noqa
from .metaGroup import metatypes_table # noqa
from .traits import traits_table # noqa
mapper(Item, items_table,
properties={"group": relation(Group, backref="items"),

View File

@@ -4,8 +4,6 @@ Migration 15
- Delete projected modules on citadels
"""
import sqlalchemy
def upgrade(saveddata_engine):
sql = """

View File

@@ -4,8 +4,6 @@ Migration 17
- Moves all fleet boosters to the new schema
"""
import sqlalchemy
def upgrade(saveddata_engine):
from eos.db import saveddata_session

View File

@@ -4,8 +4,6 @@ Migration 19
- Deletes broken references to fits from the commandFits table (see GH issue #844)
"""
import sqlalchemy
def upgrade(saveddata_engine):
from eos.db import saveddata_session

View File

@@ -17,13 +17,13 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
import sqlalchemy
from sqlalchemy.exc import DatabaseError
import logging
logger = logging.getLogger(__name__)
class DatabaseCleanup:
class DatabaseCleanup(object):
def __init__(self):
pass
@@ -32,7 +32,7 @@ class DatabaseCleanup:
try:
results = saveddata_engine.execute(query)
return results
except sqlalchemy.exc.DatabaseError:
except DatabaseError:
logger.error("Failed to connect to database or error executing query:\n%s", query)
return None
@@ -85,7 +85,8 @@ class DatabaseCleanup:
logger.error("More than one uniform damage pattern found.")
else:
uniform_damage_pattern_id = rows[0]['ID']
update_query = "UPDATE 'fits' SET 'damagePatternID' = {} WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL".format(uniform_damage_pattern_id)
update_query = "UPDATE 'fits' SET 'damagePatternID' = {} " \
"WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL".format(uniform_damage_pattern_id)
update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query)
logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount)
@@ -117,7 +118,7 @@ class DatabaseCleanup:
logger.error("More than one 'All 5' character found.")
else:
all5_id = rows[0]['ID']
update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \
update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \
" WHERE characterID not in (select ID from characters) OR characterID IS NULL"
update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query)
logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount)
@@ -166,7 +167,8 @@ class DatabaseCleanup:
# See issue #954
for table in ['drones', 'cargo', 'fighters']:
logger.debug("Running database cleanup for orphaned %s items.", table)
query = "SELECT COUNT(*) AS num FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table)
query = "SELECT COUNT(*) AS num FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(
table)
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
if results is None:
@@ -175,13 +177,15 @@ class DatabaseCleanup:
row = results.first()
if row and row['num']:
query = "DELETE FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table)
query = "DELETE FROM {} WHERE itemID IS NULL OR itemID = '' or itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(
table)
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)
for table in ['modules']:
logger.debug("Running database cleanup for orphaned %s items.", table)
query = "SELECT COUNT(*) AS num FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(table)
query = "SELECT COUNT(*) AS num FROM {} WHERE itemID = '0' or fitID IS NULL OR fitID = '' or fitID = '0'".format(
table)
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
if results is None:
@@ -201,7 +205,8 @@ class DatabaseCleanup:
for profileType in ['damagePatterns', 'targetResists']:
for damageType in ['em', 'thermal', 'kinetic', 'explosive']:
logger.debug("Running database cleanup for null %s values. (%s)", profileType, damageType)
query = "SELECT COUNT(*) AS num FROM {0} WHERE {1}Amount IS NULL OR {1}Amount = ''".format(profileType, damageType)
query = "SELECT COUNT(*) AS num FROM {0} WHERE {1}Amount IS NULL OR {1}Amount = ''".format(profileType,
damageType)
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
if results is None:
@@ -210,7 +215,8 @@ class DatabaseCleanup:
row = results.first()
if row and row['num']:
query = "UPDATE '{0}' SET '{1}Amount' = '0' WHERE {1}Amount IS NULL OR Amount = ''".format(profileType, damageType)
query = "UPDATE '{0}' SET '{1}Amount' = '0' WHERE {1}Amount IS NULL OR Amount = ''".format(profileType,
damageType)
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)

View File

@@ -140,7 +140,7 @@ mapper(es_Fit, fits_table,
"_Fit__modules": relation(
Module,
collection_class=HandledModuleList,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
order_by=modules_table.c.position,
cascade='all, delete, delete-orphan'),
"_Fit__projectedModules": relation(
@@ -148,7 +148,7 @@ mapper(es_Fit, fits_table,
collection_class=HandledProjectedModList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
"owner": relation(
User,
backref="fits"),
@@ -164,13 +164,13 @@ mapper(es_Fit, fits_table,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
"_Fit__fighters": relation(
Fighter,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
"_Fit__cargo": relation(
Cargo,
collection_class=HandledDroneCargoList,
@@ -182,13 +182,13 @@ mapper(es_Fit, fits_table,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
"_Fit__projectedFighters": relation(
Fighter,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
"_Fit__implants": relation(
Implant,
collection_class=HandledImplantBoosterList,

View File

@@ -26,7 +26,7 @@ class ImportError(Exception):
pass
class DefaultDatabaseValues():
class DefaultDatabaseValues(object):
def __init__(self):
pass

View File

@@ -68,6 +68,7 @@ if configVal is True:
def checkAndReturn(*args, **kwargs):
useCache = kwargs.pop("useCache", True)
cacheKey = []
items = None
cacheKey.extend(args)
for keyword in keywords:
cacheKey.append(kwargs.get(keyword))

View File

@@ -17,12 +17,7 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
# from sqlalchemy.orm.attributes import flag_modified
import logging
# TODO: This can't point to es_Module, cyclical import loop
# from eos.saveddata.module import Module as es_Module, State as es_State
import eos.db
logger = logging.getLogger(__name__)
@@ -141,13 +136,6 @@ class HandledModuleList(HandledList):
self.remove(mod)
return
# fix for #529, where a module may be in incorrect state after CCP changes mechanics of module
# TODO: This can't point to es_module, cyclical import loop
'''
if not mod.isValidState(mod.state):
mod.state = es_State.ONLINE
'''
def insert(self, index, mod):
mod.position = index
i = index
@@ -167,13 +155,10 @@ class HandledModuleList(HandledList):
def toDummy(self, index):
mod = self[index]
if not mod.isEmpty:
pass
# TODO: This can't point to es_Module, cyclical import loop
'''
dummy = es_Module.buildEmpty(mod.slot)
dummy = mod.buildEmpty(mod.slot)
dummy.position = index
self[index] = dummy
'''
def toModule(self, index, mod):
mod.position = index

View File

@@ -1,4 +1,4 @@
class Enum():
class Enum(object):
def __init__(self):
pass

View File

@@ -19,6 +19,8 @@
class EqBase(object):
ID = None
def __eq__(self, other):
return type(self) == type(other) and self.ID == other.ID

View File

@@ -45,6 +45,9 @@ class Effect(EqBase):
# Filter to change names of effects to valid python method names
nameFilter = re.compile("[^A-Za-z0-9]")
def __init__(self):
pass
@reconstructor
def init(self):
"""
@@ -179,7 +182,7 @@ class Effect(EqBase):
t = t if isinstance(t, tuple) or t is None else (t,)
self.__type = t
except (ImportError, AttributeError) as e:
except (ImportError, AttributeError):
self.__handler = effectDummy
self.__runTime = "normal"
self.__activeByDefault = True
@@ -207,6 +210,9 @@ class Item(EqBase):
MOVE_ATTR_INFO = None
def __init__(self):
pass
@classmethod
def getMoveAttrInfo(cls):
info = getattr(cls, "MOVE_ATTR_INFO", None)
@@ -447,6 +453,9 @@ class Category(EqBase):
class AlphaClone(EqBase):
def __init__(self):
pass
@reconstructor
def init(self):
self.skillCache = {}
@@ -474,6 +483,9 @@ class Icon(EqBase):
class MarketGroup(EqBase):
def __init__(self):
pass
def __repr__(self):
return u"MarketGroup(ID={}, name={}, parent={}) at {}".format(
self.ID, self.name, getattr(self.parent, "name", None), self.name, hex(id(self))
@@ -485,6 +497,9 @@ class MetaGroup(EqBase):
class MetaType(EqBase):
def __init__(self):
pass
pass

View File

@@ -62,7 +62,7 @@ class Data(object):
def parseString(self, dataString):
if not isinstance(dataString, basestring):
return (Constant(dataString),)
return Constant(dataString),
dataList = []
for data in dataString.split(";"):
@@ -93,7 +93,8 @@ class Constant(object):
def __iter__(self):
yield self.value
def isConstant(self):
@staticmethod
def isConstant():
return True
@@ -114,5 +115,6 @@ class Range(object):
i += 1
yield current
def isConstant(self):
@staticmethod
def isConstant():
return False

View File

@@ -38,7 +38,7 @@ class FitDpsGraph(Graph):
fit = self.fit
total = 0
distance = data["distance"] * 1000
abssort = lambda val: -abs(val - 1)
abssort = lambda _val: -abs(_val - 1)
for mod in fit.modules:
if not mod.isEmpty and mod.state >= State.ACTIVE:
@@ -95,7 +95,8 @@ class FitDpsGraph(Graph):
return total
def calculateMissileMultiplier(self, mod, data):
@staticmethod
def calculateMissileMultiplier(mod, data):
targetSigRad = data["signatureRadius"]
targetVelocity = data["velocity"]
explosionRadius = mod.getModifiedChargeAttr("aoeCloudSize")
@@ -126,7 +127,8 @@ class FitDpsGraph(Graph):
multiplier = min(1, (float(targetSigRad) / dmgScaling) ** 2)
return multiplier
def calculateFighterMissileMultiplier(self, ability, data):
@staticmethod
def calculateFighterMissileMultiplier(ability, data):
prefix = ability.attrPrefix
targetSigRad = data["signatureRadius"]
@@ -156,7 +158,8 @@ class FitDpsGraph(Graph):
return min(sigRadiusFactor, velocityFactor, 1)
def calculateTurretChanceToHit(self, mod, data):
@staticmethod
def calculateTurretChanceToHit(mod, data):
distance = data["distance"] * 1000
tracking = mod.getModifiedItemAttr("trackingSpeed")
turretOptimal = mod.maxRange
@@ -171,7 +174,8 @@ class FitDpsGraph(Graph):
return 0.5 ** (trackingEq + rangeEq)
def calculateModuleMultiplier(self, mod, data):
@staticmethod
def calculateModuleMultiplier(mod, data):
# Simplified formula, we make some assumptions about the module
# This is basically the calculateTurretChanceToHit without tracking values
distance = data["distance"] * 1000
@@ -179,4 +183,4 @@ class FitDpsGraph(Graph):
turretFalloff = mod.falloff
rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2
return 0.5 ** (rangeEq)
return 0.5 ** rangeEq

View File

@@ -43,7 +43,7 @@ class ChargeAttrShortcut(object):
class ModifiedAttributeDict(collections.MutableMapping):
OVERRIDES = False
class CalculationPlaceholder():
class CalculationPlaceholder(object):
def __init__(self):
pass
@@ -212,11 +212,11 @@ class ModifiedAttributeDict(collections.MutableMapping):
for penalizedMultipliers in penalizedMultiplierGroups.itervalues():
# A quick explanation of how this works:
# 1: Bonuses and penalties are calculated seperately, so we'll have to filter each of them
l1 = filter(lambda val: val > 1, penalizedMultipliers)
l2 = filter(lambda val: val < 1, penalizedMultipliers)
l1 = filter(lambda _val: _val > 1, penalizedMultipliers)
l2 = filter(lambda _val: _val < 1, penalizedMultipliers)
# 2: The most significant bonuses take the smallest penalty,
# This means we'll have to sort
abssort = lambda val: -abs(val - 1)
abssort = lambda _val: -abs(_val - 1)
l1.sort(key=abssort)
l2.sort(key=abssort)
# 3: The first module doesn't get penalized at all
@@ -359,7 +359,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
self.__afflict(attributeName, u"\u2263", value)
class Affliction():
class Affliction(object):
def __init__(self, type, amount):
self.type = type
self.amount = amount

View File

@@ -103,7 +103,8 @@ class Booster(HandledItem, ItemAttrShortcut):
def item(self):
return self.__item
def __calculateSlot(self, item):
@staticmethod
def __calculateSlot(item):
if "boosterness" not in item.attributes:
raise ValueError("Passed item is not a booster")
@@ -132,11 +133,11 @@ class Booster(HandledItem, ItemAttrShortcut):
@validates("ID", "itemID", "ammoID", "active")
def validator(self, key, val):
map = {"ID": lambda val: isinstance(val, int),
"itemID": lambda val: isinstance(val, int),
"ammoID": lambda val: isinstance(val, int),
"active": lambda val: isinstance(val, bool),
"slot": lambda val: isinstance(val, int) and 1 <= val <= 3}
map = {"ID": lambda _val: isinstance(_val, int),
"itemID": lambda _val: isinstance(_val, int),
"ammoID": lambda _val: isinstance(_val, int),
"active": lambda _val: isinstance(_val, bool),
"slot": lambda _val: isinstance(_val, int) and 1 <= _val <= 3}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -71,9 +71,9 @@ class Cargo(HandledItem, ItemAttrShortcut):
@validates("fitID", "itemID", "amount")
def validator(self, key, val):
map = {"fitID": lambda val: isinstance(val, int),
"itemID": lambda val: isinstance(val, int),
"amount": lambda val: isinstance(val, int)}
map = {"fitID": lambda _val: isinstance(_val, int),
"itemID": lambda _val: isinstance(_val, int),
"amount": lambda _val: isinstance(_val, int)}
if key == "amount" and val > sys.maxint:
val = sys.maxint

View File

@@ -256,10 +256,10 @@ class Character(object):
@validates("ID", "name", "apiKey", "ownerID")
def validator(self, key, val):
map = {"ID": lambda val: isinstance(val, int),
"name": lambda val: True,
"apiKey": lambda val: val is None or (isinstance(val, basestring) and len(val) > 0),
"ownerID": lambda val: isinstance(val, int) or val is None}
map = {"ID": lambda _val: isinstance(_val, int),
"name": lambda _val: True,
"apiKey": lambda _val: _val is None or (isinstance(_val, basestring) and len(_val) > 0),
"ownerID": lambda _val: isinstance(_val, int) or _val is None}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)
@@ -377,8 +377,8 @@ class Skill(HandledItem):
if hasattr(self, "_Skill__ro") and self.__ro is True and key != "characterID":
raise ReadOnlyException()
map = {"characterID": lambda val: isinstance(val, int),
"skillID": lambda val: isinstance(val, int)}
map = {"characterID": lambda _val: isinstance(_val, int),
"skillID": lambda _val: isinstance(_val, int)}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -186,11 +186,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@validates("ID", "itemID", "chargeID", "amount", "amountActive")
def validator(self, key, val):
map = {"ID": lambda val: isinstance(val, int),
"itemID": lambda val: isinstance(val, int),
"chargeID": lambda val: isinstance(val, int),
"amount": lambda val: isinstance(val, int) and val >= 0,
"amountActive": lambda val: isinstance(val, int) and self.amount >= val >= 0}
map = {"ID": lambda _val: isinstance(_val, int),
"itemID": lambda _val: isinstance(_val, int),
"chargeID": lambda _val: isinstance(_val, int),
"amount": lambda _val: isinstance(_val, int) and _val >= 0,
"amountActive": lambda _val: isinstance(_val, int) and self.amount >= _val >= 0}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -219,10 +219,10 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@validates("ID", "itemID", "chargeID", "amount", "amountActive")
def validator(self, key, val):
map = {"ID": lambda val: isinstance(val, int),
"itemID": lambda val: isinstance(val, int),
"chargeID": lambda val: isinstance(val, int),
"amount": lambda val: isinstance(val, int) and val >= -1,
map = {"ID": lambda _val: isinstance(_val, int),
"itemID": lambda _val: isinstance(_val, int),
"chargeID": lambda _val: isinstance(_val, int),
"amount": lambda _val: isinstance(_val, int) and _val >= -1,
}
if not map[key](val):

View File

@@ -17,7 +17,6 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
import copy
import time
from copy import deepcopy
from itertools import chain
@@ -27,7 +26,6 @@ from sqlalchemy.orm import validates, reconstructor
import eos.db
from eos import capSim
from eos.effectHandlerHelpers import *
from eos.effectHandlerHelpers import HandledModuleList, HandledDroneCargoList, HandledImplantBoosterList, HandledProjectedDroneList, HandledProjectedModList
from eos.enum import Enum
from eos.saveddata.ship import Ship
@@ -39,16 +37,8 @@ import logging
logger = logging.getLogger(__name__)
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
class ImplantLocation(Enum):
def __init__(self):
pass
FIT = 0
CHARACTER = 1
@@ -374,9 +364,9 @@ class Fit(object):
@validates("ID", "ownerID", "shipID")
def validator(self, key, val):
map = {"ID": lambda val: isinstance(val, int),
"ownerID": lambda val: isinstance(val, int) or val is None,
"shipID": lambda val: isinstance(val, int) or val is None}
map = {"ID": lambda _val: isinstance(_val, int),
"ownerID": lambda _val: isinstance(_val, int) or _val is None,
"shipID": lambda _val: isinstance(_val, int) or _val is None}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)
@@ -438,9 +428,11 @@ class Fit(object):
self.__modifier = currModifier
self.__origin = origin
if hasattr(currModifier, "itemModifiedAttributes"):
currModifier.itemModifiedAttributes.fit = origin or self
if hasattr(currModifier.itemModifiedAttributes, "fit"):
currModifier.itemModifiedAttributes.fit = origin or self
if hasattr(currModifier, "chargeModifiedAttributes"):
currModifier.chargeModifiedAttributes.fit = origin or self
if hasattr(currModifier.itemModifiedAttributes, "fit"):
currModifier.chargeModifiedAttributes.fit = origin or self
def getModifier(self):
return self.__modifier
@@ -651,7 +643,7 @@ class Fit(object):
shadow = True
# Don't inspect this, we genuinely want to reassign self
# noinspection PyMethodFirstArgAssignment
self = copy.deepcopy(self)
self = deepcopy(self)
logger.debug("Handling self projection - making shadow copy of fit. %r => %r", copied, self)
# we delete the fit because when we copy a fit, flush() is
# called to properly handle projection updates. However, we do
@@ -727,7 +719,7 @@ class Fit(object):
self.register(item)
item.calculateModifiedAttributes(self, runTime, False)
if projected is True and item not in chain.from_iterable(r):
if projected is True and projectionInfo and item not in chain.from_iterable(r):
# apply effects onto target fit
for _ in xrange(projectionInfo.amount):
targetFit.register(item, origin=self)
@@ -803,7 +795,8 @@ class Fit(object):
x += 1
return x
def getItemAttrSum(self, dict, attr):
@staticmethod
def getItemAttrSum(dict, attr):
amount = 0
for mod in dict:
add = mod.getModifiedItemAttr(attr)
@@ -812,7 +805,8 @@ class Fit(object):
return amount
def getItemAttrOnlineSum(self, dict, attr):
@staticmethod
def getItemAttrOnlineSum(dict, attr):
amount = 0
for mod in dict:
add = mod.getModifiedItemAttr(attr) if mod.state >= State.ONLINE else None
@@ -1047,8 +1041,8 @@ class Fit(object):
repairers.append(mod)
# Sort repairers by efficiency. We want to use the most efficient repairers first
repairers.sort(key=lambda mod: mod.getModifiedItemAttr(
groupAttrMap[mod.item.group.name]) / mod.getModifiedItemAttr("capacitorNeed"), reverse=True)
repairers.sort(key=lambda _mod: _mod.getModifiedItemAttr(
groupAttrMap[_mod.item.group.name]) / _mod.getModifiedItemAttr("capacitorNeed"), reverse=True)
# Loop through every module until we're above peak recharge
# Most efficient first, as we sorted earlier.
@@ -1263,16 +1257,16 @@ class Fit(object):
return True
def __deepcopy__(self, memo):
copy = Fit()
def __deepcopy__(self, memo=None):
copy_ship = Fit()
# Character and owner are not copied
copy.character = self.__character
copy.owner = self.owner
copy.ship = deepcopy(self.ship, memo)
copy.name = "%s copy" % self.name
copy.damagePattern = self.damagePattern
copy.targetResists = self.targetResists
copy.notes = self.notes
copy_ship.character = self.__character
copy_ship.owner = self.owner
copy_ship.ship = deepcopy(self.ship)
copy_ship.name = "%s copy" % self.name
copy_ship.damagePattern = self.damagePattern
copy_ship.targetResists = self.targetResists
copy_ship.notes = self.notes
toCopy = (
"modules",
@@ -1286,17 +1280,17 @@ class Fit(object):
"projectedFighters")
for name in toCopy:
orig = getattr(self, name)
c = getattr(copy, name)
c = getattr(copy_ship, name)
for i in orig:
c.append(deepcopy(i, memo))
c.append(deepcopy(i))
for fit in self.projectedFits:
copy.__projectedFits[fit.ID] = fit
copy_ship.__projectedFits[fit.ID] = fit
# this bit is required -- see GH issue # 83
eos.db.saveddata_session.flush()
eos.db.saveddata_session.refresh(fit)
return copy
return copy_ship
def __repr__(self):
return u"Fit(ID={}, ship={}, name={}) at {}".format(

View File

@@ -78,7 +78,8 @@ class Implant(HandledItem, ItemAttrShortcut):
def item(self):
return self.__item
def __calculateSlot(self, item):
@staticmethod
def __calculateSlot(item):
if "implantness" not in item.attributes:
raise ValueError("Passed item is not an implant")
@@ -98,9 +99,9 @@ class Implant(HandledItem, ItemAttrShortcut):
@validates("fitID", "itemID", "active")
def validator(self, key, val):
map = {"fitID": lambda val: isinstance(val, int),
"itemID": lambda val: isinstance(val, int),
"active": lambda val: isinstance(val, bool)}
map = {"fitID": lambda _val: isinstance(_val, int),
"itemID": lambda _val: isinstance(_val, int),
"active": lambda _val: isinstance(_val, bool)}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -48,13 +48,13 @@ class ImplantSet(object):
return out.strip()
def __deepcopy__(self, memo):
def __deepcopy__(self):
copy = ImplantSet(self.name)
copy.name = "%s copy" % self.name
orig = getattr(self, 'implants')
c = getattr(copy, 'implants')
for i in orig:
c.append(deepcopy(i, memo))
c.append(deepcopy(i))
return copy

View File

@@ -547,7 +547,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return validCharges
def __calculateHardpoint(self, item):
@staticmethod
def __calculateHardpoint(item):
effectHardpointMap = {"turretFitted": Hardpoint.TURRET,
"launcherFitted": Hardpoint.MISSILE}
@@ -560,7 +561,8 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return Hardpoint.NONE
def __calculateSlot(self, item):
@staticmethod
def __calculateSlot(item):
effectSlotMap = {"rigSlot": Slot.RIG,
"loPower": Slot.LOW,
"medPower": Slot.MED,
@@ -579,9 +581,9 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@validates("ID", "itemID", "ammoID")
def validator(self, key, val):
map = {"ID": lambda val: isinstance(val, int),
"itemID": lambda val: val is None or isinstance(val, int),
"ammoID": lambda val: isinstance(val, int)}
map = {"ID": lambda _val: isinstance(_val, int),
"itemID": lambda _val: _val is None or isinstance(_val, int),
"ammoID": lambda _val: isinstance(_val, int)}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -49,10 +49,10 @@ class User(object):
@validates("ID", "username", "password", "admin")
def validator(self, key, val):
map = {"ID": lambda val: isinstance(val, int),
"username": lambda val: isinstance(val, basestring),
"password": lambda val: isinstance(val, basestring) and len(val) == 96,
"admin": lambda val: isinstance(val, bool)}
map = {"ID": lambda _val: isinstance(_val, int),
"username": lambda _val: isinstance(_val, basestring),
"password": lambda _val: isinstance(_val, basestring) and len(_val) == 96,
"admin": lambda _val: isinstance(_val, bool)}
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
@@ -79,11 +80,11 @@ class PFListPane(wx.ScrolledWindow):
new_vs_x, new_vs_y = -1, -1
# is it before the left edge?
if cr.x < 0 and sppu_x > 0:
if cr.x < 0 < sppu_x:
new_vs_x = vs_x + (cr.x / sppu_x)
# is it above the top?
if cr.y < 0 and sppu_y > 0:
if cr.y < 0 < sppu_y:
new_vs_y = vs_y + (cr.y / sppu_y)
# For the right and bottom edges, scroll enough to show the
@@ -143,10 +144,8 @@ class PFListPane(wx.ScrolledWindow):
elif doFocus:
self.SetFocus()
clientW, clientH = self.GetSize()
for i in xrange(len(self._wList)):
iwidth, iheight = self._wList[i].GetSize()
itemX, itemY = self._wList[i].GetPosition()
self._wList[i].SetSize((cwidth, iheight))
if doRefresh is True:
self._wList[i].Refresh()

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
import gui.utils.colorUtils as colorUtils
import gui.utils.drawUtils as drawUtils
@@ -68,7 +69,8 @@ class PFSearchBox(wx.Window):
wx.PostEvent(self, TextEnter())
event.Skip()
def OnEditSetFocus(self, event):
@staticmethod
def OnEditSetFocus(event):
# value = self.EditBox.GetValue()
# if value == self.descriptiveText:
# self.EditBox.ChangeValue("")
@@ -102,14 +104,15 @@ class PFSearchBox(wx.Window):
x, y = target
px, py = position
aX, aY = area
if (px > x and px < x + aX) and (py > y and py < y + aY):
if (x < px < x + aX) and (y < py < y + aY):
return True
return False
def GetButtonsPos(self):
btnpos = []
btnpos.append((self.searchButtonX, self.searchButtonY))
btnpos.append((self.cancelButtonX, self.cancelButtonY))
btnpos = [
(self.searchButtonX, self.searchButtonY),
(self.cancelButtonX, self.cancelButtonY)
]
return btnpos
def GetButtonsSize(self):

View File

@@ -17,8 +17,8 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.boosterView import BoosterView
from gui.droneView import DroneView
from gui.fighterView import FighterView
@@ -31,7 +31,7 @@ from gui.notesView import NotesView
from gui.pyfatogglepanel import TogglePanel
from gui.bitmapLoader import BitmapLoader
import gui.chromeTabs
from gui.chromeTabs import PFNotebook
class AdditionsPane(TogglePanel):
@@ -45,9 +45,7 @@ class AdditionsPane(TogglePanel):
baseSizer = wx.BoxSizer(wx.HORIZONTAL)
pane.SetSizer(baseSizer)
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.notebook = gui.chromeTabs.PFNotebook(pane, False)
self.notebook = PFNotebook(pane, False)
self.notebook.SetMinSize((-1, 1000))
baseSizer.Add(self.notebook, 1, wx.EXPAND)
@@ -92,9 +90,6 @@ class AdditionsPane(TogglePanel):
def select(self, name):
self.notebook.SetSelection(self.PANES.index(name))
def toggleBoosters(self, event):
self.notebook.ToggleShown(self.booster)
def getName(self, idx):
return self.PANES[idx]

View File

@@ -22,6 +22,7 @@ import os.path
import zipfile
from config import parsePath
# noinspection PyPackageRequirements
import wx
import config
@@ -32,7 +33,7 @@ except ImportError:
from utils.compat import OrderedDict
class BitmapLoader():
class BitmapLoader(object):
try:
archive = zipfile.ZipFile(config.getPyfaPath('imgs.zip'), 'r')
except IOError:

View File

@@ -17,18 +17,19 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
import gui.globalEvents as GE
import gui.marketBrowser as mb
import gui.marketBrowser as marketBrowser
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from service.fit import Fit
class BoosterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
def __init__(self, dropFn, *args, **kwargs):
super(BoosterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
@@ -52,7 +53,7 @@ class BoosterView(d.Display):
self.lastFitId = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
@@ -66,16 +67,16 @@ class BoosterView(d.Display):
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def handleListDrag(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "market":
wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1])))
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
def kbEvent(self, event):
keycode = event.GetKeyCode()

View File

@@ -1,5 +1,6 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from service.fit import Fit

View File

@@ -2,6 +2,7 @@ from gui.contextMenu import ContextMenu
from eos.saveddata.fit import Fit as es_Fit
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
from eos.saveddata.cargo import Cargo as es_Cargo
@@ -49,7 +50,6 @@ class AmountChanger(wx.Dialog):
self.button.Bind(wx.EVT_BUTTON, self.change)
def change(self, event):
sFit = Fit.getInstance()
if self.input.GetLineText(0).strip() == '':
event.Skip()
return
@@ -70,7 +70,8 @@ class AmountChanger(wx.Dialog):
event.Skip()
# checks to make sure it's valid number
def onChar(self, event):
@staticmethod
def onChar(event):
key = event.GetKeyCode()
acceptable_characters = "1234567890"

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.fit import Fit

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from eos.saveddata.character import Skill

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from service.fit import Fit
@@ -9,7 +10,7 @@ from service.damagePattern import DamagePattern as import_DamagePattern
try:
from collections import OrderedDict
except ImportError:
from gui.utils.compat import OrderedDict
from utils.compat import OrderedDict
class DamagePattern(ContextMenu):

View File

@@ -1,5 +1,6 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from service.fit import Fit

View File

@@ -2,6 +2,7 @@ from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
from service.fit import Fit
# noinspection PyPackageRequirements
import wx

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from service.fit import Fit

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.contextMenu import ContextMenu
import gui.mainFrame

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.implantSet import ImplantSets as s_ImplantSets
from service.character import Character

View File

@@ -1,5 +1,6 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from service.fit import Fit

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
from gui.itemStats import ItemStatsDialog
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
from service.fit import Fit

View File

@@ -1,5 +1,6 @@
# coding: utf-8
# noinspection PyPackageRequirements
import wx
from service.fit import Fit

View File

@@ -1,5 +1,6 @@
# coding: utf-8
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
@@ -96,7 +97,8 @@ class ModuleAmmoPicker(ContextMenu):
return chargeDamageType, totalDamage
def numericConverter(self, string):
@staticmethod
def numericConverter(string):
return int(string) if string.isdigit() else string
def nameSorter(self, charge):
@@ -117,7 +119,8 @@ class ModuleAmmoPicker(ContextMenu):
return item
def addSeperator(self, m, text):
@staticmethod
def addSeperator(m, text):
id_ = ContextMenu.nextID()
m.Append(id_, u'%s' % text)
m.Enable(id_, False)
@@ -157,7 +160,7 @@ class ModuleAmmoPicker(ContextMenu):
item = self.addCharge(rootMenu if msw else m, charge)
items.append(item)
else:
if sub is None:
if sub is None and item and base:
sub = wx.Menu()
sub.Bind(wx.EVT_MENU, self.handleAmmoSwitch)
self.addSeperator(sub, "Less Damage")

View File

@@ -1,14 +1,16 @@
# -*- coding: utf-8 -*-
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from gui.builtinContextMenus.moduleAmmoPicker import ModuleAmmoPicker
import eos.db
from eos.db.saveddata.queries import getFit as db_getFit
from service.fit import Fit
class ModuleGlobalAmmoPicker(ModuleAmmoPicker):
def __init__(self):
super(ModuleGlobalAmmoPicker, self).__init__()
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getText(self, itmContext, selection):
@@ -26,7 +28,7 @@ class ModuleGlobalAmmoPicker(ModuleAmmoPicker):
sFit = Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
fit = eos.db.getFit(fitID)
fit = db_getFit(fitID)
selectedModule = self.modules[0]
allModules = []

View File

@@ -1,5 +1,6 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
from gui.shipBrowser import FitSelected

View File

@@ -1,5 +1,6 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
from service.market import Market

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.fit import Fit

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.contextMenu import ContextMenu
import gui.mainFrame

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.contextMenu import ContextMenu
import gui.mainFrame

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
from service.targetResists import TargetResists as svc_TargetResists
@@ -9,7 +10,7 @@ from service.fit import Fit
try:
from collections import OrderedDict
except ImportError:
from gui.utils.compat import OrderedDict
from utils.compat import OrderedDict
class TargetResists(ContextMenu):

View File

@@ -1,6 +1,7 @@
from gui.contextMenu import ContextMenu
import gui.mainFrame
import gui.globalEvents as GE
# noinspection PyPackageRequirements
import wx
from service.market import Market
from service.fit import Fit

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
__all__ = ["pyfaGeneralPreferences", "pyfaHTMLExportPreferences", "pyfaUpdatePreferences",

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
@@ -7,6 +8,7 @@ import gui.mainFrame
from service.settings import CRESTSettings
# noinspection PyPackageRequirements
from wx.lib.intctrl import IntCtrl
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# noinspection PyPackageRequirements
import wx
import copy
@@ -425,7 +426,8 @@ class PFGaugePref(PreferenceView):
self.SetColours()
event.Skip()
def OnOk(self, event):
@staticmethod
def OnOk(event):
# Apply New Settings
event.Skip()

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
import os

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.preferenceView import PreferenceView
@@ -39,7 +40,7 @@ class PFUpdatePref(PreferenceView):
mainSizer.Add(self.suppressPrerelease, 0, wx.ALL | wx.EXPAND, 5)
if (self.UpdateSettings.get('version')):
if self.UpdateSettings.get('version'):
self.versionSizer = wx.BoxSizer(wx.VERTICAL)
self.versionTitle = wx.StaticText(panel, wx.ID_ANY, "Suppressing {0} Notifications".format(

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
@@ -130,8 +131,8 @@ class CapacitorViewFull(StatsView):
capStable = fit.capStable if fit is not None else False
lblNameTime = "label%sCapacitorTime"
lblNameState = "label%sCapacitorState"
if isinstance(capState, tuple):
t = "%.1f%%-%.1f%%" % capState
if isinstance(capState, tuple) and len(capState) >= 2:
t = ("{0}%-{1}%", capState[0], capState[1])
s = ""
else:
if capStable:

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.statsView import StatsView

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.statsView import StatsView

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
@@ -74,8 +75,7 @@ class PriceViewFull(StatsView):
if fit is not None:
self.fit = fit
# Compose a list of all the data we need & request it
typeIDs = []
typeIDs.append(fit.ship.item.ID)
typeIDs = [fit.ship.item.ID]
for mod in fit.modules:
if not mod.isEmpty:

View File

@@ -17,12 +17,13 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
from gui.utils.numberFormatter import formatAmount
import gui.mainFrame
import gui.builtinStatsViews.resistancesViewFull as rvf
from gui.builtinStatsViews.resistancesViewFull import EFFECTIVE_HP_TOGGLED
from service.fit import Fit
@@ -33,7 +34,7 @@ class RechargeViewFull(StatsView):
StatsView.__init__(self)
self.parent = parent
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.mainFrame.Bind(rvf.EFFECTIVE_HP_TOGGLED, self.toggleEffective)
self.mainFrame.Bind(EFFECTIVE_HP_TOGGLED, self.toggleEffective)
self.effective = True
def getHeaderText(self, fit):

View File

@@ -17,10 +17,11 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
from gui import pygauge as PG
from gui.pygauge import PyGauge
from gui.utils.numberFormatter import formatAmount
import gui.mainFrame
import gui.globalEvents as GE
@@ -132,7 +133,7 @@ class ResistancesViewFull(StatsView):
bc = pgColour[1]
currGColour += 1
lbl = PG.PyGauge(contentPanel, wx.ID_ANY, 100)
lbl = PyGauge(contentPanel, wx.ID_ANY, 100)
lbl.SetMinSize((48, 16))
lbl.SetBackgroundColour(wx.Colour(bc[0], bc[1], bc[2]))
lbl.SetBarColour(wx.Colour(fc[0], fc[1], fc[2]))

View File

@@ -17,12 +17,13 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui.bitmapLoader import BitmapLoader
from gui import pygauge as PG
from gui.pygauge import PyGauge
import gui.mainFrame
import gui.chromeTabs
from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED
from eos.saveddata.module import Hardpoint
@@ -37,7 +38,7 @@ class ResourcesViewFull(StatsView):
StatsView.__init__(self)
self.parent = parent
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.mainFrame.additionsPane.notebook.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.mainFrame.additionsPane.notebook.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
def pageChanged(self, event):
page = self.mainFrame.additionsPane.getName(event.GetSelection())
@@ -175,7 +176,7 @@ class ResourcesViewFull(StatsView):
# Gauges modif. - Darriele
gauge = PG.PyGauge(parent, wx.ID_ANY, 1)
gauge = PyGauge(parent, wx.ID_ANY, 1)
gauge.SetValueRange(0, 0)
gauge.SetMinSize((self.getTextExtentW("1.999M/1.99M MW"), 23))
gauge.SetFractionDigits(2)
@@ -216,52 +217,61 @@ class ResourcesViewFull(StatsView):
("label%sTotalCargoBay", lambda: fit.ship.getModifiedItemAttr("capacity"), 3, 0, 9),
)
panel = "Full"
usedTurretHardpoints = 0
labelUTH = ""
totalTurretHardpoints = 0
labelTTH = ""
usedLauncherHardpoints = 0
labelULH = ""
totalLauncherHardPoints = 0
labelTLH = ""
usedDronesActive = 0
labelUDA = ""
totalDronesActive = 0
labelTDA = ""
usedFighterTubes = 0
labelUFT = ""
totalFighterTubes = 0
labelTFT = ""
usedCalibrationPoints = 0
labelUCP = ""
totalCalibrationPoints = 0
labelTCP = ""
for labelName, value, prec, lowest, highest in stats:
label = getattr(self, labelName % panel)
value = value() if fit is not None else 0
value = value if value is not None else 0
if labelName % panel == "label%sUsedTurretHardpoints" % panel:
usedTurretHardpoints = value
labelUTH = label
if labelName % panel == "label%sTotalTurretHardpoints" % panel:
elif labelName % panel == "label%sTotalTurretHardpoints" % panel:
totalTurretHardpoints = value
labelTTH = label
if labelName % panel == "label%sUsedLauncherHardpoints" % panel:
elif labelName % panel == "label%sUsedLauncherHardpoints" % panel:
usedLauncherHardpoints = value
labelULH = label
if labelName % panel == "label%sTotalLauncherHardpoints" % panel:
elif labelName % panel == "label%sTotalLauncherHardpoints" % panel:
totalLauncherHardPoints = value
labelTLH = label
if labelName % panel == "label%sUsedDronesActive" % panel:
elif labelName % panel == "label%sUsedDronesActive" % panel:
usedDronesActive = value
labelUDA = label
if labelName % panel == "label%sTotalDronesActive" % panel:
elif labelName % panel == "label%sTotalDronesActive" % panel:
totalDronesActive = value
labelTDA = label
if labelName % panel == "label%sUsedFighterTubes" % panel:
elif labelName % panel == "label%sUsedFighterTubes" % panel:
usedFighterTubes = value
labelUFT = label
if labelName % panel == "label%sTotalFighterTubes" % panel:
elif labelName % panel == "label%sTotalFighterTubes" % panel:
totalFighterTubes = value
labelTFT = label
if labelName % panel == "label%sUsedCalibrationPoints" % panel:
elif labelName % panel == "label%sUsedCalibrationPoints" % panel:
usedCalibrationPoints = value
labelUCP = label
if labelName % panel == "label%sTotalCalibrationPoints" % panel:
elif labelName % panel == "label%sTotalCalibrationPoints" % panel:
totalCalibrationPoints = value
labelTCP = label
@@ -316,6 +326,8 @@ class ResourcesViewFull(StatsView):
lambda: fit.ship.getModifiedItemAttr("droneBandwidth"),
lambda: fit.ship.getModifiedItemAttr("capacity"),
)
else:
resMax = None
i = 0
for resourceType in ("cpu", "pg", "droneBay", "fighterBay", "droneBandwidth", "cargoBay"):

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.statsView import StatsView
from gui.utils.numberFormatter import formatAmount
@@ -202,16 +203,14 @@ class TargetingMiscViewFull(StatsView):
label.SetToolTip(
wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance)))
else:
label.SetToolTip(wx.ToolTip("Type: %s" % (fit.scanType)))
label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType))
elif labelName == "labelFullAlignTime":
alignTime = "Align:\t%.3fs" % mainValue
mass = 'Mass:\t{:,.0f}kg'.format(fit.ship.getModifiedItemAttr("mass"))
agility = "Agility:\t%.3fx" % (fit.ship.getModifiedItemAttr("agility") or 0)
label.SetToolTip(wx.ToolTip("%s\n%s\n%s" % (alignTime, mass, agility)))
elif labelName == "labelFullCargo":
tipLines = []
tipLines.append(
u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, newValues["main"]))
tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, newValues["main"])]
for attrName, tipAlias in cargoNamesOrder.items():
if newValues[attrName] > 0:
tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, newValues[attrName]))
@@ -231,7 +230,7 @@ class TargetingMiscViewFull(StatsView):
if fit.jamChance > 0:
label.SetToolTip(wx.ToolTip("Type: %s\n%.1f%% Chance of Jam" % (fit.scanType, fit.jamChance)))
else:
label.SetToolTip(wx.ToolTip("Type: %s" % (fit.scanType)))
label.SetToolTip(wx.ToolTip("Type: %s" % fit.scanType))
else:
label.SetToolTip(wx.ToolTip(""))
elif labelName == "labelFullCargo":
@@ -239,9 +238,7 @@ class TargetingMiscViewFull(StatsView):
cachedCargo = self._cachedValues[counter]
# if you add stuff to cargo, the capacity doesn't change and thus it is still cached
# This assures us that we force refresh of cargo tooltip
tipLines = []
tipLines.append(
u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, cachedCargo["main"]))
tipLines = [u"Cargohold: {:,.2f}m\u00B3 / {:,.2f}m\u00B3".format(fit.cargoBayUsed, cachedCargo["main"])]
for attrName, tipAlias in cargoNamesOrder.items():
if cachedCargo[attrName] > 0:
tipLines.append(u"{}: {:,.2f}m\u00B3".format(tipAlias, cachedCargo[attrName]))

View File

@@ -18,6 +18,7 @@
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.fighter import Fighter
from gui.viewColumn import ViewColumn

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.fighter import Fighter
from gui.viewColumn import ViewColumn

View File

@@ -18,6 +18,7 @@
# =============================================================================
from gui.viewColumn import ViewColumn
# noinspection PyPackageRequirements
import wx
from eos.saveddata.module import Module

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.viewColumn import ViewColumn
@@ -82,7 +83,7 @@ class AttributeDisplay(ViewColumn):
if self.info.name == "volume":
str_ = (formatAmount(attr, 3, 0, 3))
if hasattr(mod, "amount"):
str_ = str_ + u"m\u00B3 (%s m\u00B3)" % (formatAmount(attr * mod.amount, 3, 0, 3))
str_ += u"m\u00B3 (%s m\u00B3)" % (formatAmount(attr * mod.amount, 3, 0, 3))
attr = str_
if isinstance(attr, (float, int)):

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from eos.saveddata.implant import Implant
from eos.saveddata.drone import Drone

View File

@@ -18,6 +18,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.cargo import Cargo
from eos.saveddata.implant import Implant

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.mode import Mode

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.mode import Mode
@@ -73,7 +74,7 @@ class MaxRange(ViewColumn):
return -1
def getParameters(self):
return (("displayName", bool, False), ("showIcon", bool, True))
return ("displayName", bool, False), ("showIcon", bool, True)
def getToolTip(self, mod):
return "Optimal + Falloff"

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from service.fit import Fit
@@ -58,7 +59,7 @@ class Miscellanea(ViewColumn):
return -1
def getParameters(self):
return (("displayName", bool, False), ("showIcon", bool, True))
return ("displayName", bool, False), ("showIcon", bool, True)
def __getData(self, stuff):
item = stuff.item
@@ -504,8 +505,8 @@ class Miscellanea(ViewColumn):
for number_of_cycles in {5, 10, 25}:
tooltip = "{0}\n{1} charges lasts {2} seconds ({3} cycles)".format(
tooltip,
formatAmount(number_of_cycles*cycles, 3, 0, 3),
formatAmount((duration+reload_time)*number_of_cycles, 3, 0, 3),
formatAmount(number_of_cycles * cycles, 3, 0, 3),
formatAmount((duration + reload_time) * number_of_cycles, 3, 0, 3),
formatAmount(number_of_cycles, 3, 0, 3)
)
text = "{0} / {1}s (+{2}s)".format(

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.cargo import Cargo

View File

@@ -56,7 +56,7 @@ class PropertyDisplay(ViewColumn):
def getText(self, stuff):
attr = getattr(stuff, self.propertyName, None)
if attr:
return (formatAmount(attr, 3, 0, 3))
return formatAmount(attr, 3, 0, 3)
else:
return ""

View File

@@ -18,6 +18,7 @@
# =============================================================================
# noinspection PyPackageRequirements
import wx
from eos.saveddata.fit import Fit

View File

@@ -1,6 +1,7 @@
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import gui.chromeTabs
from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED
import gui.mainFrame
@@ -11,13 +12,13 @@ class BlankPage(wx.Panel):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
self.parent = parent
self.parent.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=None))
def Destroy(self):
self.parent.Unbind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
wx.Panel.Destroy(self)
def pageChanged(self, event):

View File

@@ -1,3 +1,4 @@
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader

View File

@@ -17,7 +17,9 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
import wx.lib.newevent
import gui.mainFrame
import gui.marketBrowser
@@ -31,7 +33,8 @@ from gui.builtinViewColumns.state import State
from gui.bitmapLoader import BitmapLoader
import gui.builtinViews.emptyView
from gui.utils.exportHtml import exportHtml
from logging import getLogger, Formatter
from logging import getLogger
from gui.chromeTabs import EVT_NOTEBOOK_PAGE_CHANGED
from service.fit import Fit
from service.market import Market
@@ -97,8 +100,8 @@ FitSpawner.register()
# Drag'n'drop handler
class FittingViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
def __init__(self, dropFn, *args, **kwargs):
super(FittingViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
@@ -157,7 +160,7 @@ class FittingView(d.Display):
self.Bind(wx.EVT_SHOW, self.OnShow)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
self.parent.Bind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
self.parent.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.pageChanged)
def OnLeaveWindow(self, event):
self.SetToolTip(None)
@@ -185,13 +188,13 @@ class FittingView(d.Display):
event.Skip()
def handleListDrag(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two items:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "fitting":
self.swapItems(x, y, int(data[1]))
@@ -206,7 +209,7 @@ class FittingView(d.Display):
wx.PostEvent(self.mainFrame, gui.shipBrowser.FitSelected(fitID=fitID))
def Destroy(self):
self.parent.Unbind(gui.chromeTabs.EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged)
self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.fitChanged)
self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_RENAMED, handler=self.fitRenamed)
self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_REMOVED, handler=self.fitRemoved)
@@ -259,11 +262,11 @@ class FittingView(d.Display):
event.Skip()
def fitRemoved(self, event):
'''
"""
If fit is removed and active, the page is deleted.
We also refresh the fit of the new current page in case
delete fit caused change in stats (projected)
'''
"""
fitID = event.fitID
if fitID == self.getActiveFit():
@@ -355,7 +358,7 @@ class FittingView(d.Display):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID))
def addModule(self, x, y, srcIdx):
'''Add a module from the market browser'''
"""Add a module from the market browser"""
dstRow, _ = self.HitTest((x, y))
if dstRow != -1 and dstRow not in self.blanks:
@@ -368,7 +371,7 @@ class FittingView(d.Display):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def swapCargo(self, x, y, srcIdx):
'''Swap a module from cargo to fitting window'''
"""Swap a module from cargo to fitting window"""
mstate = wx.GetMouseState()
dstRow, _ = self.HitTest((x, y))
@@ -382,7 +385,7 @@ class FittingView(d.Display):
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
def swapItems(self, x, y, srcIdx):
'''Swap two modules in fitting window'''
"""Swap two modules in fitting window"""
mstate = wx.GetMouseState()
sFit = Fit.getInstance()
fit = sFit.getFit(self.activeFitID)
@@ -403,20 +406,23 @@ class FittingView(d.Display):
if mod1.slot != mod2.slot:
return
if clone and mod2.isEmpty:
sFit.cloneModule(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
else:
sFit.swapModules(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
if getattr(mod2, "modPosition"):
if clone and mod2.isEmpty:
sFit.cloneModule(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
else:
sFit.swapModules(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
else:
logger.error("Missing module position for: %s", str(getattr(mod2, "ID", "Unknown")))
def generateMods(self):
'''
"""
Generate module list.
This also injects dummy modules to visually separate racks. These modules are only
known to the display, and not the backend, so it's safe.
'''
"""
sFit = Fit.getInstance()
fit = sFit.getFit(self.activeFitID)
@@ -425,7 +431,7 @@ class FittingView(d.Display):
if fit is not None:
self.mods = fit.modules[:]
self.mods.sort(key=lambda mod: (slotOrder.index(mod.slot), mod.position))
self.mods.sort(key=lambda _mod: (slotOrder.index(_mod.slot), _mod.position))
# Blanks is a list of indexes that mark non-module positions (such
# as Racks and tactical Modes. This allows us to skip over common
@@ -536,13 +542,13 @@ class FittingView(d.Display):
self.PopupMenu(menu)
def click(self, event):
'''
"""
Handle click event on modules.
This is only useful for the State column. If multiple items are selected,
and we have clicked the State column, iterate through the selections and
change State
'''
"""
row, _, col = self.HitTestSubItem(event.Position)
# only do State column and ignore invalid rows
@@ -584,12 +590,12 @@ class FittingView(d.Display):
return self.slotColourMap.get(slot) or self.GetBackgroundColour()
def refresh(self, stuff):
'''
"""
Displays fitting
Sends data to d.Display.refresh where the rows and columns are set up, then does a
bit of post-processing (colors)
'''
"""
self.Freeze()
d.Display.refresh(self, stuff)
@@ -644,6 +650,7 @@ class FittingView(d.Display):
def Snapshot(self):
return self.FVsnapshot
# noinspection PyPropertyAccess
def MakeSnapshot(self, maxColumns=1337):
if self.FVsnapshot:
@@ -677,7 +684,6 @@ class FittingView(d.Display):
isize = 16
headerSize = max(isize, tdc.GetTextExtent("W")[0]) + padding * 2
maxWidth = 0
maxRowHeight = isize
rows = 0
for st in self.mods:
@@ -741,7 +747,7 @@ class FittingView(d.Display):
maxWidth += columnsWidths[i]
mdc = wx.MemoryDC()
mbmp = wx.EmptyBitmap(maxWidth, (maxRowHeight) * rows + padding * 4 + headerSize)
mbmp = wx.EmptyBitmap(maxWidth, maxRowHeight * rows + padding * 4 + headerSize)
mdc.SelectObject(mbmp)
@@ -771,8 +777,7 @@ class FittingView(d.Display):
bmp = col.bitmap
opts.m_labelBitmap = bmp
width = render.DrawHeaderButton(self, mdc, (cx, padding, columnsWidths[i], headerSize), wx.CONTROL_CURRENT,
sortArrow=wx.HDR_SORT_ICON_NONE, params=opts)
render.DrawHeaderButton(self, mdc, (cx, padding, columnsWidths[i], headerSize), wx.CONTROL_CURRENT, sortArrow=wx.HDR_SORT_ICON_NONE, params=opts)
cx += columnsWidths[i]

View File

@@ -1,4 +1,6 @@
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
from wx.lib.buttons import GenBitmapButton
from service.market import Market

View File

@@ -18,6 +18,7 @@
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
from gui.builtinViewColumns.state import State
@@ -27,8 +28,8 @@ from service.market import Market
class CargoViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
def __init__(self, dropFn, *args, **kwargs):
super(CargoViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
@@ -66,13 +67,13 @@ class CargoView(d.Display):
self.Bind(wx.EVT_RIGHT_DOWN, self.scheduleMenu)
def handleListDrag(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "fitting":
self.swapModule(x, y, int(data[1]))
@@ -104,7 +105,7 @@ class CargoView(d.Display):
event.Skip()
def swapModule(self, x, y, modIdx):
'''Swap a module from fitting window with cargo'''
"""Swap a module from fitting window with cargo"""
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
dstRow, _ = self.HitTest((x, y))

View File

@@ -17,9 +17,12 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
import wx.lib.newevent
# noinspection PyPackageRequirements
import wx.gizmos
from gui.bitmapLoader import BitmapLoader
from gui.contextMenu import ContextMenu
@@ -625,9 +628,9 @@ class APIView(wx.Panel):
try:
activeChar = self.charEditor.entityEditor.getActiveEntity()
list = sChar.apiCharList(activeChar.ID, self.inputID.GetLineText(0), self.inputKey.GetLineText(0))
except AuthenticationError, e:
except AuthenticationError:
self.stStatus.SetLabel("Authentication failure. Please check keyID and vCode combination.")
except TimeoutError, e:
except TimeoutError:
self.stStatus.SetLabel("Request timed out. Please check network connectivity and/or proxy settings.")
except Exception, e:
self.stStatus.SetLabel("Error:\n%s" % e.message)

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from gui.bitmapLoader import BitmapLoader
import gui.globalEvents as GE

View File

@@ -17,7 +17,9 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
# noinspection PyPackageRequirements
import wx.lib.newevent
import gui.utils.colorUtils as colorUtils
import gui.utils.drawUtils as drawUtils
@@ -34,7 +36,7 @@ PageAdded, EVT_NOTEBOOK_PAGE_ADDED = wx.lib.newevent.NewEvent()
PageClosed, EVT_NOTEBOOK_PAGE_CLOSED = wx.lib.newevent.NewEvent()
class VetoAble():
class VetoAble(object):
def __init__(self):
self.__vetoed = False
@@ -45,7 +47,7 @@ class VetoAble():
return self.__vetoed
class NotebookTabChangeEvent():
class NotebookTabChangeEvent(object):
def __init__(self, old, new):
self.__old = old
self.__new = new
@@ -146,7 +148,8 @@ class PFNotebook(wx.Panel):
if self.activePage == page:
self.ShowActive()
def GetBorders(self):
@staticmethod
def GetBorders():
"""Gets border widths to better determine page size in ShowActive()"""
bx = wx.SystemSettings_GetMetric(wx.SYS_BORDER_X)
@@ -335,7 +338,7 @@ class PFNotebook(wx.Panel):
event.Skip()
class PFTabRenderer:
class PFTabRenderer(object):
def __init__(self, size=(36, 24), text=wx.EmptyString, img=None, inclination=6, closeButton=True):
"""
Renders a new tab
@@ -438,7 +441,8 @@ class PFTabRenderer:
def SetTabImage(self, img):
self.tabImg = img
def CopyRegion(self, region):
@staticmethod
def CopyRegion(region):
rect = region.GetBox()
newRegion = wx.Region(rect.X, rect.Y, rect.Width, rect.Height)
@@ -527,8 +531,8 @@ class PFTabRenderer:
self.tabRegion = wx.RegionFromBitmap(self.tabBackBitmap)
self.closeBtnRegion = wx.RegionFromBitmap(self.ctabCloseBmp)
self.closeBtnRegion.Offset(
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2,
(self.tabHeight - self.ctabCloseBmp.GetHeight()) / 2
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2,
(self.tabHeight - self.ctabCloseBmp.GetHeight()) / 2
)
def InitColors(self):
@@ -591,9 +595,9 @@ class PFTabRenderer:
cbmp = wx.BitmapFromImage(cimg)
mdc.DrawBitmap(
cbmp,
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2,
(height - self.ctabCloseBmp.GetHeight()) / 2,
cbmp,
self.contentWidth + self.leftWidth - self.ctabCloseBmp.GetWidth() / 2,
(height - self.ctabCloseBmp.GetHeight()) / 2,
)
mdc.SelectObject(wx.NullBitmap)
@@ -609,11 +613,11 @@ class PFTabRenderer:
def __repr__(self):
return "PFTabRenderer(text={}, disabled={}) at {}".format(
self.text, self.disabled, hex(id(self))
self.text, self.disabled, hex(id(self))
)
class PFAddRenderer:
class PFAddRenderer(object):
def __init__(self):
"""Renders the add tab button"""
self.addImg = BitmapLoader.getImage("ctabadd", "gui")
@@ -652,7 +656,8 @@ class PFAddRenderer:
region = wx.RegionFromBitmap(self.tbmp)
return region
def CopyRegion(self, region):
@staticmethod
def CopyRegion(region):
rect = region.GetBox()
newRegion = wx.Region(rect.X, rect.Y, rect.Width, rect.Height)
@@ -973,7 +978,8 @@ class PFTabsContainer(wx.Panel):
return tab
return None
def TabHitTest(self, tab, x, y):
@staticmethod
def TabHitTest(tab, x, y):
tabRegion = tab.GetTabRegion()
tabPos = tab.GetPosition()
tabPosX, tabPosY = tabPos
@@ -1117,13 +1123,13 @@ class PFTabsContainer(wx.Panel):
else:
mdc = wx.BufferedPaintDC(self)
selected = 0
if 'wxMac' in wx.PlatformInfo and wx.VERSION < (3, 0):
color = wx.Colour(0, 0, 0)
brush = wx.Brush(color)
# noinspection PyPackageRequirements,PyUnresolvedReferences,PyUnresolvedReferences,PyUnresolvedReferences
from Carbon.Appearance import kThemeBrushDialogBackgroundActive
# noinspection PyUnresolvedReferences
brush.MacSetTheme(kThemeBrushDialogBackgroundActive)
else:
color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
@@ -1253,7 +1259,7 @@ class PFTabsContainer(wx.Panel):
if self.tabMinWidth < 1:
self.tabMinWidth = 1
for tab in self.tabs:
w, h = tab.GetSize()
tab.GetSize()
tab.SetSize((self.tabMinWidth, self.height))
if self.GetTabsCount() > 0:
@@ -1268,6 +1274,7 @@ class PFTabsContainer(wx.Panel):
pos = tabsWidth
selected = None
selpos = None
for i in range(len(self.tabs) - 1, -1, -1):
tab = self.tabs[i]
width = tab.tabWidth - self.inclination * 2

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.display as d
import gui.globalEvents as GE
@@ -28,20 +29,20 @@ from service.fit import Fit
from eos.saveddata.drone import Drone as es_Drone
class DummyItem:
class DummyItem(object):
def __init__(self, txt):
self.name = txt
self.icon = None
class DummyEntry:
class DummyEntry(object):
def __init__(self, txt):
self.item = DummyItem(txt)
class CommandViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
def __init__(self, dropFn, *args, **kwargs):
super(CommandViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
@@ -78,14 +79,15 @@ class CommandView(d.Display):
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.startDrag)
self.SetDropTarget(CommandViewDrop(self.handleListDrag))
def handleListDrag(self, x, y, data):
'''
@staticmethod
def handleListDrag(x, y, data):
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
pass
def kbEvent(self, event):
@@ -118,7 +120,8 @@ class CommandView(d.Display):
dropSource.SetData(data)
dropSource.DoDragDrop()
def fitSort(self, fit):
@staticmethod
def fitSort(fit):
return fit.name
def fitChanged(self, event):
@@ -151,7 +154,7 @@ class CommandView(d.Display):
self.deselectItems()
# todo: verify
if stuff == []:
if not stuff:
stuff = [DummyEntry("Drag a fit to this area")]
self.update(stuff)
@@ -159,7 +162,7 @@ class CommandView(d.Display):
def get(self, row):
numFits = len(self.fits)
if (numFits) == 0:
if numFits == 0:
return None
return self.fits[row]
@@ -191,7 +194,7 @@ class CommandView(d.Display):
fitSrcContext = "commandFit"
fitItemContext = item.name
context = ((fitSrcContext, fitItemContext),)
context = context + (("command",),)
context += ("command",),
menu = ContextMenu.getMenu((item,), *context)
elif sel == -1:
fitID = self.mainFrame.getActiveFit()

View File

@@ -17,6 +17,7 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import logging
@@ -58,7 +59,7 @@ class ContextMenu(object):
rootMenu.selection = (selection,) if not hasattr(selection, "__iter__") else selection
empty = True
for i, fullContext in enumerate(fullContexts):
amount = 0
display_amount = 0
srcContext = fullContext[0]
try:
itemContext = fullContext[1]
@@ -68,7 +69,7 @@ class ContextMenu(object):
# loop through registered menus
m = menuHandler()
if m.display(srcContext, selection):
amount += 1
display_amount += 1
texts = m.getText(itemContext, selection)
if isinstance(texts, basestring):
@@ -115,11 +116,11 @@ class ContextMenu(object):
empty = False
if amount > 0 and i != len(fullContexts) - 1:
if display_amount > 0 and i != len(fullContexts) - 1:
rootMenu.AppendSeparator()
debug_end = len(cls._ids)
if (debug_end - debug_start):
if debug_end - debug_start:
logger.debug("%d new IDs created for this menu" % (debug_end - debug_start))
return rootMenu if empty is False else None
@@ -177,4 +178,29 @@ class ContextMenu(object):
return None
from gui.builtinContextMenus import * # noqa
# noinspection PyUnresolvedReferences
from gui.builtinContextMenus import ( # noqa: E402,F401
ammoPattern,
amount,
cargo,
changeAffectingSkills,
damagePattern,
droneRemoveStack,
droneSplit,
factorReload,
fighterAbilities,
implantSets,
itemRemove,
itemStats,
marketJump,
metaSwap,
moduleAmmoPicker,
moduleGlobalAmmoPicker,
openFit,
priceClear,
project,
shipJump,
tacticalMode,
targetResists,
whProjector
)

View File

@@ -18,6 +18,7 @@
# =============================================================================
# noinspection PyPackageRequirements
import wx
@@ -53,7 +54,7 @@ class CopySelectDialog(wx.Dialog):
mainSizer.Add(selector, 0, wx.EXPAND | wx.ALL, 5)
buttonSizer = self.CreateButtonSizer(wx.OK | wx.CANCEL)
if (buttonSizer):
if buttonSizer:
mainSizer.Add(buttonSizer, 0, wx.EXPAND | wx.ALL, 5)
self.SetSizer(mainSizer)

View File

@@ -1,6 +1,7 @@
import time
import webbrowser
import json
# noinspection PyPackageRequirements
import wx
import requests
@@ -10,7 +11,7 @@ from service.fit import Fit
from eos.saveddata.cargo import Cargo
from eos.db import getItem
import gui.display as d
from gui.display import Display
import gui.globalEvents as GE
if 'wxMac' not in wx.PlatformInfo or ('wxMac' in wx.PlatformInfo and wx.VERSION >= (3, 0)):
@@ -144,10 +145,9 @@ class CrestFittings(wx.Frame):
self.updateCacheStatus(None)
self.cacheTimer.Start(1000)
self.fitTree.populateSkillTree(fittings)
del waitDialog
except requests.exceptions.ConnectionError:
self.statusbar.SetStatusText("Connection error, please check your internet connection")
finally:
del waitDialog
def importFitting(self, event):
selection = self.fitView.fitSelection
@@ -340,7 +340,8 @@ class CrestMgmt(wx.Dialog):
self.lcCharacters.SetColumnWidth(0, wx.LIST_AUTOSIZE)
self.lcCharacters.SetColumnWidth(1, wx.LIST_AUTOSIZE)
def addChar(self, event):
@staticmethod
def addChar(event):
sCrest = Crest.getInstance()
uri = sCrest.startServer()
webbrowser.open(uri)
@@ -411,10 +412,10 @@ class FittingsTreeView(wx.Panel):
self.parent.fitView.update(list)
class FitView(d.Display):
class FitView(Display):
DEFAULT_COLS = ["Base Icon",
"Base Name"]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
Display.__init__(self, parent, style=wx.LC_SINGLE_SEL)
self.fitSelection = None

View File

@@ -18,6 +18,7 @@
# =============================================================================
import sys
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.viewColumn import ViewColumn
@@ -25,6 +26,8 @@ from gui.cachingImageList import CachingImageList
class Display(wx.ListCtrl):
DEFAULT_COLS = None
def __init__(self, parent, size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, size=size, style=wx.LC_REPORT | style)
@@ -64,6 +67,7 @@ class Display(wx.ListCtrl):
i += 1
info = wx.ListItem()
# noinspection PyPropertyAccess
info.m_mask = wx.LIST_MASK_WIDTH
self.InsertColumnInfo(i, info)
self.SetColumnWidth(i, 0)
@@ -88,11 +92,11 @@ class Display(wx.ListCtrl):
# Did the point hit any item?
if (flags & wx.LIST_HITTEST_ONITEM) == 0:
return (-1, 0, -1)
return -1, 0, -1
# If it did hit an item and we are not in report mode, it must be the primary cell
if not self.InReportView():
return (rowIndex, wx.LIST_HITTEST_ONITEM, 0)
return rowIndex, wx.LIST_HITTEST_ONITEM, 0
# Find which subitem is hit
right = 0
@@ -105,9 +109,9 @@ class Display(wx.ListCtrl):
flag = wx.LIST_HITTEST_ONITEMICON
else:
flag = wx.LIST_HITTEST_ONITEMLABEL
return (rowIndex, flag, i)
return rowIndex, flag, i
return (rowIndex, 0, -1)
return rowIndex, 0, -1
def OnEraseBk(self, event):
if self.GetItemCount() > 0:
@@ -143,6 +147,7 @@ class Display(wx.ListCtrl):
else:
event.Skip()
# noinspection PyPropertyAccess
def addColumn(self, i, col):
self.activeColumns.append(col)
info = wx.ListItem()
@@ -217,7 +222,7 @@ class Display(wx.ListCtrl):
self.InsertStringItem(sys.maxint, "")
if listItemCount > stuffItemCount:
if listItemCount - stuffItemCount > 20 and stuffItemCount < 20:
if listItemCount - stuffItemCount > 20 > stuffItemCount:
self.DeleteAllItems()
for i in range(stuffItemCount):
self.InsertStringItem(sys.maxint, "")

View File

@@ -17,11 +17,12 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import gui.marketBrowser as mb
import gui.display as d
from gui.marketBrowser import ITEM_SELECTED, ItemSelected
from gui.display import Display
from gui.builtinViewColumns.state import State
from gui.contextMenu import ContextMenu
from service.fit import Fit
@@ -29,8 +30,8 @@ from service.market import Market
class DroneViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
def __init__(self, dropFn, *args, **kwargs):
super(DroneViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
@@ -43,7 +44,7 @@ class DroneViewDrop(wx.PyDropTarget):
return t
class DroneView(d.Display):
class DroneView(Display):
DEFAULT_COLS = [
"State",
# "Base Icon",
@@ -56,7 +57,7 @@ class DroneView(d.Display):
]
def __init__(self, parent):
d.Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
Display.__init__(self, parent, style=wx.LC_SINGLE_SEL | wx.BORDER_NONE)
self.lastFitId = None
@@ -64,7 +65,7 @@ class DroneView(d.Display):
self.hoveredColumn = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
self.mainFrame.Bind(ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
@@ -128,20 +129,20 @@ class DroneView(d.Display):
dropSource.DoDragDrop()
def handleDragDrop(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "drone": # we want to merge drones
srcRow = int(data[1])
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
elif data[0] == "market":
wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1])))
wx.PostEvent(self.mainFrame, ItemSelected(itemID=int(data[1])))
def _merge(self, src, dst):
sFit = Fit.getInstance()

View File

@@ -17,10 +17,11 @@
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.globalEvents as GE
import gui.marketBrowser as mb
import gui.marketBrowser as marketBrowser
import gui.mainFrame
import gui.display as d
from gui.builtinViewColumns.state import State
@@ -31,8 +32,8 @@ from service.market import Market
class FighterViewDrop(wx.PyDropTarget):
def __init__(self, dropFn):
wx.PyDropTarget.__init__(self)
def __init__(self, dropFn, *args, **kwargs):
super(FighterViewDrop, self).__init__(*args, **kwargs)
self.dropFn = dropFn
# this is really transferring an EVE itemID
self.dropData = wx.PyTextDataObject()
@@ -126,7 +127,7 @@ class FighterDisplay(d.Display):
self.hoveredColumn = None
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
self.mainFrame.Bind(mb.ITEM_SELECTED, self.addItem)
self.mainFrame.Bind(marketBrowser.ITEM_SELECTED, self.addItem)
self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem)
self.Bind(wx.EVT_LEFT_DOWN, self.click)
self.Bind(wx.EVT_KEY_UP, self.kbEvent)
@@ -190,22 +191,23 @@ class FighterDisplay(d.Display):
dropSource.DoDragDrop()
def handleDragDrop(self, x, y, data):
'''
"""
Handles dragging of items from various pyfa displays which support it
data is list with two indices:
data[0] is hard-coded str of originating source
data[1] is typeID or index of data we want to manipulate
'''
"""
if data[0] == "fighter": # we want to merge fighters
srcRow = int(data[1])
dstRow, _ = self.HitTest((x, y))
if srcRow != -1 and dstRow != -1:
self._merge(srcRow, dstRow)
elif data[0] == "market":
wx.PostEvent(self.mainFrame, mb.ItemSelected(itemID=int(data[1])))
wx.PostEvent(self.mainFrame, marketBrowser.ItemSelected(itemID=int(data[1])))
def _merge(self, src, dst):
@staticmethod
def _merge(src, dst):
return
'''

Some files were not shown because too many files have changed in this diff Show More