Merge branch 'development'
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -4,8 +4,6 @@ Migration 15
|
||||
- Delete projected modules on citadels
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
sql = """
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -26,7 +26,7 @@ class ImportError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DefaultDatabaseValues():
|
||||
class DefaultDatabaseValues(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Enum():
|
||||
class Enum(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
|
||||
class EqBase(object):
|
||||
ID = None
|
||||
|
||||
def __eq__(self, other):
|
||||
return type(self) == type(other) and self.ID == other.ID
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user