Merge branch 'development'

This commit is contained in:
blitzman
2017-02-11 21:42:48 -05:00
158 changed files with 1255 additions and 1036 deletions

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)
@@ -800,7 +792,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)
@@ -809,7 +802,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
@@ -1044,8 +1038,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.
@@ -1260,16 +1254,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",
@@ -1283,17 +1277,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)