Merge tag 'v2.0.1' into singularity (bring sisi code up to date with pyfa 2 / py3 / wx4)

# Conflicts:
#	eos/effects/techtwocommandburstbonus.py
This commit is contained in:
blitzmann
2018-05-15 01:17:51 -04:00
258 changed files with 6365 additions and 9307 deletions

View File

@@ -1,6 +1,7 @@
import heapq
import time
from math import sqrt, exp
from functools import reduce
DAY = 24 * 60 * 60 * 1000
@@ -88,7 +89,7 @@ class CapSimulator(object):
mods[(duration, capNeed, clipSize, disableStagger, reloadTime)] = 1
# Loop over grouped modules, configure staggering and push to the simulation state
for (duration, capNeed, clipSize, disableStagger, reloadTime), amount in mods.iteritems():
for (duration, capNeed, clipSize, disableStagger, reloadTime), amount in mods.items():
if self.stagger and not disableStagger:
if clipSize == 0:
duration = int(duration / amount)
@@ -193,7 +194,7 @@ class CapSimulator(object):
# calculate EVE's stability value
try:
avgDrain = reduce(float.__add__, map(lambda x: x[2] / x[1], self.state), 0.0)
avgDrain = reduce(float.__add__, [x[2] / x[1] for x in self.state], 0.0)
self.cap_stable_eve = 0.25 * (1.0 + sqrt(-(2.0 * avgDrain * tau - capCapacity) / capCapacity)) ** 2
except ValueError:
self.cap_stable_eve = 0.0

View File

@@ -11,14 +11,14 @@ debug = False
gamedataCache = True
saveddataCache = True
gamedata_version = ""
gamedata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "eve.db")), sys.getfilesystemencoding())
gamedata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "eve.db"))
pyfalog.debug("Gamedata connection string: {0}", gamedata_connectionstring)
if istravis is True or hasattr(sys, '_called_from_test'):
# Running in Travis. Run saveddata database in memory.
saveddata_connectionstring = 'sqlite:///:memory:'
else:
saveddata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata.db")), sys.getfilesystemencoding())
saveddata_connectionstring = 'sqlite:///' + realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata-py3-db.db"))
pyfalog.debug("Saveddata connection string: {0}", saveddata_connectionstring)
@@ -28,4 +28,4 @@ settings = {
}
# Autodetect path, only change if the autodetection bugs out.
path = dirname(unicode(__file__, sys.getfilesystemencoding()))
path = dirname(__file__)

View File

@@ -22,7 +22,7 @@ import threading
from sqlalchemy import MetaData, create_engine
from sqlalchemy.orm import sessionmaker
import migration
from . import migration
from eos import config
from logbook import Logger
@@ -76,7 +76,7 @@ sd_lock = threading.RLock()
# 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, \
from eos.db.saveddata import booster, cargo, character, damagePattern, databaseRepair, drone, fighter, fit, implant, implantSet, loadDefaultDatabaseValues, \
miscData, module, override, price, queries, skill, targetResists, user
# Import queries

View File

@@ -81,7 +81,7 @@ def getItem(lookfor, eager=None):
item = gamedata_session.query(Item).get(lookfor)
else:
item = gamedata_session.query(Item).options(*processEager(eager)).filter(Item.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in itemNameMap:
id = itemNameMap[lookfor]
if eager is None:
@@ -154,7 +154,7 @@ def getGroup(lookfor, eager=None):
group = gamedata_session.query(Group).get(lookfor)
else:
group = gamedata_session.query(Group).options(*processEager(eager)).filter(Group.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in groupNameMap:
id = groupNameMap[lookfor]
if eager is None:
@@ -181,7 +181,7 @@ def getCategory(lookfor, eager=None):
else:
category = gamedata_session.query(Category).options(*processEager(eager)).filter(
Category.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in categoryNameMap:
id = categoryNameMap[lookfor]
if eager is None:
@@ -210,7 +210,7 @@ def getMetaGroup(lookfor, eager=None):
else:
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(
MetaGroup.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
if lookfor in metaGroupNameMap:
id = metaGroupNameMap[lookfor]
if eager is None:
@@ -245,7 +245,7 @@ def getMarketGroup(lookfor, eager=None):
def getItemsByCategory(filter, where=None, eager=None):
if isinstance(filter, int):
filter = Category.ID == filter
elif isinstance(filter, basestring):
elif isinstance(filter, str):
filter = Category.name == filter
else:
raise TypeError("Need integer or string as argument")
@@ -257,7 +257,7 @@ def getItemsByCategory(filter, where=None, eager=None):
@cachedQuery(3, "where", "nameLike", "join")
def searchItems(nameLike, where=None, join=None, eager=None):
if not isinstance(nameLike, basestring):
if not isinstance(nameLike, str):
raise TypeError("Need string as argument")
if join is None:
@@ -268,7 +268,7 @@ def searchItems(nameLike, where=None, join=None, eager=None):
items = gamedata_session.query(Item).options(*processEager(eager)).join(*join)
for token in nameLike.split(' '):
token_safe = u"%{0}%".format(sqlizeString(token))
token_safe = "%{0}%".format(sqlizeString(token))
if where is not None:
items = items.filter(and_(Item.name.like(token_safe, escape="\\"), where))
else:
@@ -279,12 +279,12 @@ def searchItems(nameLike, where=None, join=None, eager=None):
@cachedQuery(3, "where", "nameLike", "join")
def searchSkills(nameLike, where=None, eager=None):
if not isinstance(nameLike, basestring):
if not isinstance(nameLike, str):
raise TypeError("Need string as argument")
items = gamedata_session.query(Item).options(*processEager(eager)).join(Item.group, Group.category)
for token in nameLike.split(' '):
token_safe = u"%{0}%".format(sqlizeString(token))
token_safe = "%{0}%".format(sqlizeString(token))
if where is not None:
items = items.filter(and_(Item.name.like(token_safe, escape="\\"), Category.ID == 16, where))
else:
@@ -322,7 +322,7 @@ def getVariations(itemids, groupIDs=None, where=None, eager=None):
@cachedQuery(1, "attr")
def getAttributeInfo(attr, eager=None):
if isinstance(attr, basestring):
if isinstance(attr, str):
filter = AttributeInfo.name == attr
elif isinstance(attr, int):
filter = AttributeInfo.ID == attr
@@ -337,7 +337,7 @@ def getAttributeInfo(attr, eager=None):
@cachedQuery(1, "field")
def getMetaData(field):
if isinstance(field, basestring):
if isinstance(field, str):
data = gamedata_session.query(MetaData).get(field)
else:
raise TypeError("Need string as argument")
@@ -367,7 +367,7 @@ def getRequiredFor(itemID, attrMapping):
skillToLevelClauses = []
for attrSkill, attrLevel in attrMapping.iteritems():
for attrSkill, attrLevel in attrMapping.items():
skillToLevelClauses.append(and_(Attribute1.attributeID == attrSkill, Attribute2.attributeID == attrLevel))
queryOr = or_(*skillToLevelClauses)

View File

@@ -3,7 +3,7 @@ import shutil
import time
import config
import migrations
from . import migrations
pyfalog = Logger(__name__)
@@ -34,7 +34,7 @@ def update(saveddata_engine):
shutil.copyfile(config.saveDB, toFile)
for version in xrange(dbVersion, appVersion):
for version in range(dbVersion, appVersion):
func = migrations.updates[version + 1]
if func:
pyfalog.info("Applying database update: {0}", version + 1)

View File

@@ -15,7 +15,27 @@ updates = {}
appVersion = 0
prefix = __name__ + "."
for importer, modname, ispkg in pkgutil.iter_modules(__path__, prefix):
# load modules to work based with and without pyinstaller
# from: https://github.com/webcomics/dosage/blob/master/dosagelib/loader.py
# see: https://github.com/pyinstaller/pyinstaller/issues/1905
# load modules using iter_modules()
# (should find all filters in normal build, but not pyinstaller)
module_names = [m[1] for m in pkgutil.iter_modules(__path__, prefix)]
# special handling for PyInstaller
importers = map(pkgutil.get_importer, __path__)
toc = set()
for i in importers:
if hasattr(i, 'toc'):
toc |= i.toc
for elm in toc:
if elm.startswith(prefix):
module_names.append(elm)
for modname in module_names:
# loop through python files, extracting update number and function, and
# adding it to a list
modname_tail = modname.rsplit('.', 1)[-1]

View File

@@ -91,7 +91,7 @@ def upgrade(saveddata_engine):
saveddata_engine.execute("ALTER TABLE fits ADD COLUMN targetResistsID INTEGER;")
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -108,7 +108,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -332,7 +332,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -60,7 +60,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -29,7 +29,7 @@ def upgrade(saveddata_engine):
"targetResists": 2
}
for table in tables.keys():
for table in list(tables.keys()):
# midnight brain, there's probably a much more simple way to do this, but fuck it
if tables[table] > 0:

View File

@@ -4204,7 +4204,7 @@ conversion2 = {
def upgrade(saveddata_engine):
# First we want to get a list of fittings that are completely fitted out with subsystems
oldItems = [str(x) for x in conversion2.iterkeys()]
oldItems = [str(x) for x in conversion2.keys()]
# I can't figure out a way to get IN operator to work when supplying a list using a parameterized query. So I'm
# doing it the shitty way by formatting the SQL string. Don't do this kids!
@@ -4239,7 +4239,7 @@ def upgrade(saveddata_engine):
# if something fails, fuck it, we tried. It'll default to the generic conversion below
continue
for oldItem, newItem in conversion2.iteritems():
for oldItem, newItem in conversion2.items():
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(newItem, oldItem))
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',

View File

@@ -133,7 +133,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -17,7 +17,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert ships
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "fits" SET "shipID" = ? WHERE "shipID" = ?',
(replacement_item, retired_item))

View File

@@ -77,7 +77,7 @@ CONVERSIONS = {
def upgrade(saveddata_engine):
# Convert modules
for replacement_item, list in CONVERSIONS.iteritems():
for replacement_item, list in CONVERSIONS.items():
for retired_item in list:
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
(replacement_item, retired_item))

View File

@@ -12,7 +12,6 @@ __all__ = [
"miscData",
"targetResists",
"override",
"crest",
"implantSet",
"loadDefaultDatabaseValues"
]

View File

@@ -17,24 +17,24 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Float
from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Float, UniqueConstraint
from sqlalchemy.orm import relation, mapper
import datetime
from eos.db import saveddata_meta
from eos.db.saveddata.implant import charImplants_table
from eos.effectHandlerHelpers import HandledImplantBoosterList
from eos.effectHandlerHelpers import HandledImplantBoosterList, HandledSsoCharacterList
from eos.saveddata.implant import Implant
from eos.saveddata.user import User
from eos.saveddata.character import Character, Skill
from eos.saveddata.ssocharacter import SsoCharacter
characters_table = Table("characters", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("name", String, nullable=False),
Column("apiID", Integer),
Column("apiKey", String),
Column("defaultChar", Integer),
Column("chars", String, nullable=True),
Column("defaultLevel", Integer, nullable=True),
Column("alphaCloneID", Integer, nullable=True),
Column("ownerID", ForeignKey("users.ID"), nullable=True),
@@ -42,6 +42,28 @@ characters_table = Table("characters", saveddata_meta,
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
sso_table = Table("ssoCharacter", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("client", String, nullable=False),
Column("characterID", Integer, nullable=False),
Column("characterName", String, nullable=False),
Column("refreshToken", String, nullable=False),
Column("accessToken", String, nullable=False),
Column("accessTokenExpires", DateTime, nullable=False),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
UniqueConstraint('client', 'characterID', name='uix_client_characterID'),
UniqueConstraint('client', 'characterName', name='uix_client_characterName')
)
sso_character_map_table = Table("ssoCharacterMap", saveddata_meta,
Column("characterID", ForeignKey("characters.ID"), primary_key=True),
Column("ssoCharacterID", ForeignKey("ssoCharacter.ID"), primary_key=True),
)
mapper(SsoCharacter, sso_table)
mapper(Character, characters_table,
properties={
"_Character__alphaCloneID": characters_table.c.alphaCloneID,
@@ -63,5 +85,10 @@ mapper(Character, characters_table,
primaryjoin=charImplants_table.c.charID == characters_table.c.ID,
secondaryjoin=charImplants_table.c.implantID == Implant.ID,
secondary=charImplants_table),
"_Character__ssoCharacters" : relation(
SsoCharacter,
collection_class=HandledSsoCharacterList,
backref='characters',
secondary=sso_character_map_table)
}
)

View File

@@ -1,34 +0,0 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from sqlalchemy import Table, Column, Integer, String, DateTime
from sqlalchemy.orm import mapper
import datetime
from eos.db import saveddata_meta
from eos.saveddata.crestchar import CrestChar
crest_table = Table("crest", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("name", String, nullable=False, unique=True),
Column("refresh_token", String, nullable=False),
# These records aren't updated. Instead, they are dropped and created, hence we don't have a modified field
Column("created", DateTime, nullable=True, default=datetime.datetime.now))
mapper(CrestChar, crest_table)

View File

@@ -27,7 +27,7 @@ from eos.db.saveddata.fit import projectedFits_table
from eos.db.util import processEager, processWhere
from eos.saveddata.price import Price
from eos.saveddata.user import User
from eos.saveddata.crestchar import CrestChar
from eos.saveddata.ssocharacter import SsoCharacter
from eos.saveddata.damagePattern import DamagePattern
from eos.saveddata.targetResists import TargetResists
from eos.saveddata.character import Character
@@ -109,9 +109,9 @@ if configVal is True:
if type not in queryCache:
return
functionCache = queryCache[type]
for _, localCache in functionCache.iteritems():
for _, localCache in functionCache.items():
toDelete = set()
for cacheKey, info in localCache.iteritems():
for cacheKey, info in localCache.items():
IDs = info[1]
if ID in IDs:
toDelete.add(cacheKey)
@@ -156,7 +156,7 @@ def getUser(lookfor, eager=None):
eager = processEager(eager)
with sd_lock:
user = saveddata_session.query(User).options(*eager).filter(User.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
user = saveddata_session.query(User).options(*eager).filter(User.username == lookfor).first()
@@ -175,7 +175,7 @@ def getCharacter(lookfor, eager=None):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(Character).options(*eager).filter(Character.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(Character).options(*eager).filter(
@@ -337,7 +337,7 @@ def clearPrices():
def getMiscData(field):
if isinstance(field, basestring):
if isinstance(field, str):
with sd_lock:
data = saveddata_session.query(MiscData).get(field)
else:
@@ -391,7 +391,7 @@ def getDamagePattern(lookfor, eager=None):
with sd_lock:
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
DamagePattern.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
@@ -412,7 +412,7 @@ def getTargetResists(lookfor, eager=None):
with sd_lock:
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
TargetResists.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
@@ -433,7 +433,7 @@ def getImplantSet(lookfor, eager=None):
with sd_lock:
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(
TargetResists.ID == lookfor).first()
elif isinstance(lookfor, basestring):
elif isinstance(lookfor, str):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(TargetResists.name == lookfor).first()
@@ -443,10 +443,10 @@ def getImplantSet(lookfor, eager=None):
def searchFits(nameLike, where=None, eager=None):
if not isinstance(nameLike, basestring):
if not isinstance(nameLike, str):
raise TypeError("Need string as argument")
# Prepare our string for request
nameLike = u"%{0}%".format(sqlizeString(nameLike))
nameLike = "%{0}%".format(sqlizeString(nameLike))
# Add any extra components to the search to our where clause
filter = processWhere(Fit.name.like(nameLike, escape="\\"), where)
@@ -467,29 +467,28 @@ def getProjectedFits(fitID):
raise TypeError("Need integer as argument")
def getCrestCharacters(eager=None):
def getSsoCharacters(clientHash, eager=None):
eager = processEager(eager)
with sd_lock:
characters = saveddata_session.query(CrestChar).options(*eager).all()
characters = saveddata_session.query(SsoCharacter).filter(SsoCharacter.client == clientHash).options(*eager).all()
return characters
@cachedQuery(CrestChar, 1, "lookfor")
def getCrestCharacter(lookfor, eager=None):
@cachedQuery(SsoCharacter, 1, "lookfor", "clientHash")
def getSsoCharacter(lookfor, clientHash, eager=None):
filter = SsoCharacter.client == clientHash
if isinstance(lookfor, int):
if eager is None:
with sd_lock:
character = saveddata_session.query(CrestChar).get(lookfor)
else:
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(CrestChar).options(*eager).filter(CrestChar.ID == lookfor).first()
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(CrestChar).options(*eager).filter(CrestChar.name == lookfor).first()
filter = and_(filter, SsoCharacter.ID == lookfor)
elif isinstance(lookfor, str):
filter = and_(filter, SsoCharacter.characterName == lookfor)
else:
raise TypeError("Need integer or string as argument")
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(SsoCharacter).options(*eager).filter(filter).first()
return character
@@ -515,8 +514,8 @@ def removeInvalid(fits):
invalids = [f for f in fits if f.isInvalid]
if invalids:
map(fits.remove, invalids)
map(saveddata_session.delete, invalids)
list(map(fits.remove, invalids))
list(map(saveddata_session.delete, invalids))
saveddata_session.commit()
return fits
@@ -544,7 +543,7 @@ def commit():
try:
saveddata_session.commit()
saveddata_session.flush()
except Exception:
except Exception as ex:
saveddata_session.rollback()
exc_info = sys.exc_info()
raise exc_info[0], exc_info[1], exc_info[2]
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])

View File

@@ -39,7 +39,7 @@ def processEager(eager):
return tuple()
else:
l = []
if isinstance(eager, basestring):
if isinstance(eager, str):
eager = (eager,)
for e in eager:
@@ -50,7 +50,7 @@ def processEager(eager):
def _replacements(eagerString):
splitEager = eagerString.split(".")
for i in xrange(len(splitEager)):
for i in range(len(splitEager)):
part = splitEager[i]
replacement = replace.get(part)
if replacement:

View File

@@ -115,7 +115,7 @@ class HandledList(list):
class HandledModuleList(HandledList):
def append(self, mod):
emptyPosition = float("Inf")
for i in xrange(len(self)):
for i in range(len(self)):
currMod = self[i]
if currMod.isEmpty and not mod.isEmpty and currMod.slot == mod.slot:
currPos = mod.position or i
@@ -149,7 +149,7 @@ class HandledModuleList(HandledList):
oldPos = mod.position
mod.position = None
for i in xrange(oldPos, len(self)):
for i in range(oldPos, len(self)):
self[i].position -= 1
def toDummy(self, index):
@@ -205,6 +205,16 @@ class HandledImplantBoosterList(HandledList):
HandledList.append(self, thing)
class HandledSsoCharacterList(list):
def append(self, character):
old = next((x for x in self if x.client == character.client), None)
if old is not None:
pyfalog.warning("Removing SSO Character with same hash: {}".format(repr(old)))
list.remove(self, old)
list.append(self, character)
class HandledProjectedModList(HandledList):
def append(self, proj):
if proj.isInvalid:

View File

@@ -10,4 +10,6 @@ type = "passive"
def handler(fit, module, context):
fit.ship.multiplyItemAttr("capacitorCapacity", module.getModifiedItemAttr("capacitorCapacityMultiplier"))
# We default this to None as there are times when the source attribute doesn't exist (for example, Cap Power Relay).
# It will return 0 as it doesn't exist, which would nullify whatever the target attribute is
fit.ship.multiplyItemAttr("capacitorCapacity", module.getModifiedItemAttr("capacitorCapacityMultiplier", None))

View File

@@ -6,6 +6,6 @@ type = "active"
def handler(fit, module, context):
for x in xrange(1, 4):
for x in range(1, 4):
value = module.getModifiedChargeAttr("warfareBuff{}Multiplier".format(x))
module.multiplyItemAttr("warfareBuff{}Value".format(x), value)

View File

@@ -8,7 +8,7 @@ type = "passive"
def handler(fit, container, context):
level = container.level if "skill" in context else 1
for i in xrange(5):
for i in range(5):
attr = "boosterEffectChance{0}".format(i + 1)
fit.boosters.filteredItemBoost(lambda booster: attr in booster.itemModifiedAttributes,
attr, container.getModifiedItemAttr("boosterChanceBonus") * level)

View File

@@ -16,7 +16,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -7,7 +7,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedChargeAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedChargeAttr("warfareBuff{}ID".format(x))

View File

@@ -6,7 +6,7 @@ type = "active", "gang"
def handler(fit, module, context, **kwargs):
for x in xrange(1, 5):
for x in range(1, 5):
if module.getModifiedItemAttr("warfareBuff{}ID".format(x)):
value = module.getModifiedItemAttr("warfareBuff{}Value".format(x))
id = module.getModifiedItemAttr("warfareBuff{}ID".format(x))

View File

@@ -9,4 +9,6 @@ type = "passive"
def handler(fit, module, context):
fit.ship.multiplyItemAttr("powerOutput", module.getModifiedItemAttr("powerOutputMultiplier"))
# We default this to None as there are times when the source attribute doesn't exist (for example, Cap Power Relay).
# It will return 0 as it doesn't exist, which would nullify whatever the target attribute is
fit.ship.multiplyItemAttr("powerOutput", module.getModifiedItemAttr("powerOutputMultiplier", None))

View File

@@ -9,4 +9,6 @@ type = "passive"
def handler(fit, module, context):
fit.ship.multiplyItemAttr("shieldCapacity", module.getModifiedItemAttr("shieldCapacityMultiplier"))
# We default this to None as there are times when the source attribute doesn't exist (for example, Cap Power Relay).
# It will return 0 as it doesn't exist, which would nullify whatever the target attribute is
fit.ship.multiplyItemAttr("shieldCapacity", module.getModifiedItemAttr("shieldCapacityMultiplier", None))

View File

View File

@@ -1,7 +1,3 @@
# warpDisruptSphere
#
# Used by:
# Modules from group: Warp Disrupt Field Generator (7 of 7)
# warpDisruptSphere
#

View File

@@ -16,7 +16,10 @@ def handler(fit, module, context):
# this is such a dirty hack
for mod in fit.modules:
if not mod.isEmpty and mod.item.requiresSkill("High Speed Maneuvering") and mod.state > State.ONLINE:
if not mod.isEmpty and mod.state > State.ONLINE and (
mod.item.requiresSkill("Micro Jump Drive Operation")
or mod.item.requiresSkill("High Speed Maneuvering")
):
mod.state = State.ONLINE
if not mod.isEmpty and mod.item.requiresSkill("Micro Jump Drive Operation") and mod.state > State.ONLINE:
mod.state = State.ONLINE

View File

@@ -58,7 +58,7 @@ def rel_listener(target, value, initiator):
if not target or (isinstance(value, Module) and value.isEmpty):
return
print "{} has had a relationship change :D".format(target)
print("{} has had a relationship change :D".format(target))
target.modified = datetime.datetime.now()

View File

@@ -22,13 +22,10 @@ import re
from sqlalchemy.orm import reconstructor
import eos.db
from eqBase import EqBase
from .eqBase import EqBase
from eos.saveddata.price import Price as types_Price
from collections import OrderedDict
try:
from collections import OrderedDict
except ImportError:
from utils.compat import OrderedDict
from logbook import Logger
@@ -160,8 +157,6 @@ class Effect(EqBase):
if it doesn't, set dummy values and add a dummy handler
"""
pyfalog.debug("Generate effect handler for {}".format(self.name))
try:
self.__effectModule = effectModule = __import__('eos.effects.' + self.handlerName, fromlist=True)
self.__handler = getattr(effectModule, "handler", effectDummy)
@@ -258,7 +253,7 @@ class Item(EqBase):
return default
def isType(self, type):
for effect in self.effects.itervalues():
for effect in self.effects.values():
if effect.isType(type):
return True
@@ -299,7 +294,7 @@ class Item(EqBase):
self.__requiredSkills = requiredSkills
# Map containing attribute IDs we may need for required skills
# { requiredSkillX : requiredSkillXLevel }
combinedAttrIDs = set(self.srqIDMap.iterkeys()).union(set(self.srqIDMap.itervalues()))
combinedAttrIDs = set(self.srqIDMap.keys()).union(set(self.srqIDMap.values()))
# Map containing result of the request
# { attributeID : attributeValue }
skillAttrs = {}
@@ -309,7 +304,7 @@ class Item(EqBase):
attrVal = attrInfo[2]
skillAttrs[attrID] = attrVal
# Go through all attributeID pairs
for srqIDAtrr, srqLvlAttr in self.srqIDMap.iteritems():
for srqIDAtrr, srqLvlAttr in self.srqIDMap.items():
# Check if we have both in returned result
if srqIDAtrr in skillAttrs and srqLvlAttr in skillAttrs:
skillID = int(skillAttrs[srqIDAtrr])
@@ -383,7 +378,7 @@ class Item(EqBase):
race = None
# Check primary and secondary required skills' races
if race is None:
skillRaces = tuple(filter(lambda rid: rid, (s.raceID for s in tuple(self.requiredSkills.keys()))))
skillRaces = tuple([rid for rid in (s.raceID for s in tuple(self.requiredSkills.keys())) if rid])
if sum(skillRaces) in map:
race = map[sum(skillRaces)]
if race == "angelserp":
@@ -405,7 +400,7 @@ class Item(EqBase):
if self.__assistive is None:
assistive = False
# Go through all effects and find first assistive
for effect in self.effects.itervalues():
for effect in self.effects.values():
if effect.isAssistance is True:
# If we find one, stop and mark item as assistive
assistive = True
@@ -420,7 +415,7 @@ class Item(EqBase):
if self.__offensive is None:
offensive = False
# Go through all effects and find first offensive
for effect in self.effects.itervalues():
for effect in self.effects.values():
if effect.isOffensive is True:
# If we find one, stop and mark item as offensive
offensive = True
@@ -429,8 +424,8 @@ class Item(EqBase):
return self.__offensive
def requiresSkill(self, skill, level=None):
for s, l in self.requiredSkills.iteritems():
if isinstance(skill, basestring):
for s, l in self.requiredSkills.items():
if isinstance(skill, str):
if s.name == skill and (level is None or l == level):
return True
@@ -468,7 +463,7 @@ class Item(EqBase):
return self.__price
def __repr__(self):
return u"Item(ID={}, name={}) at {}".format(
return "Item(ID={}, name={}) at {}".format(
self.ID, self.name, hex(id(self))
)
@@ -522,9 +517,9 @@ class Icon(EqBase):
class MarketGroup(EqBase):
def __repr__(self):
return u"MarketGroup(ID={}, name={}, parent={}) at {}".format(
return "MarketGroup(ID={}, name={}, parent={}) at {}".format(
self.ID, self.name, getattr(self.parent, "name", None), self.name, hex(id(self))
).encode('utf8')
)
class MetaGroup(EqBase):

View File

@@ -25,7 +25,7 @@ class Graph(object):
self.fit = fit
self.data = {}
if data is not None:
for name, d in data.iteritems():
for name, d in data.items():
self.setData(Data(name, d))
self.function = function
@@ -39,7 +39,7 @@ class Graph(object):
def getIterator(self):
pointNames = []
pointIterators = []
for data in self.data.itervalues():
for data in self.data.values():
pointNames.append(data.name)
pointIterators.append(data)
@@ -48,7 +48,7 @@ class Graph(object):
def _iterator(self, pointNames, pointIterators):
for pointValues in itertools.product(*pointIterators):
point = {}
for i in xrange(len(pointValues)):
for i in range(len(pointValues)):
point[pointNames[i]] = pointValues[i]
yield point, self.function(point)
@@ -61,12 +61,12 @@ class Data(object):
self.data = self.parseString(dataString)
def parseString(self, dataString):
if not isinstance(dataString, basestring):
if not isinstance(dataString, str):
return Constant(dataString),
dataList = []
for data in dataString.split(";"):
if isinstance(data, basestring) and "-" in data:
if isinstance(data, str) and "-" in data:
# Dealing with a range
dataList.append(Range(data, self.step))
else:
@@ -85,7 +85,7 @@ class Data(object):
class Constant(object):
def __init__(self, const):
if isinstance(const, basestring):
if isinstance(const, str):
self.value = None if const == "" else float(const)
else:
self.value = const

View File

@@ -63,10 +63,10 @@ class FitDpsGraph(Graph):
ew['signatureRadius'].sort(key=abssort)
ew['velocity'].sort(key=abssort)
for attr, values in ew.iteritems():
for attr, values in ew.items():
val = data[attr]
try:
for i in xrange(len(values)):
for i in range(len(values)):
bonus = values[i]
val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
data[attr] = val
@@ -81,7 +81,7 @@ class FitDpsGraph(Graph):
total += dps * self.calculateTurretMultiplier(mod, data)
elif mod.hardpoint == Hardpoint.MISSILE:
if mod.state >= State.ACTIVE and mod.maxRange >= distance:
if mod.state >= State.ACTIVE and mod.maxRange is not None and mod.maxRange >= distance:
total += dps * self.calculateMissileMultiplier(mod, data)
if distance <= fit.extraAttributes["droneControlRange"]:

View File

@@ -28,23 +28,17 @@ cappingAttrKeyCache = {}
class ItemAttrShortcut(object):
def getModifiedItemAttr(self, key, default=None):
def getModifiedItemAttr(self, key, default=0):
return_value = self.itemModifiedAttributes.get(key)
if return_value is None and default is not None:
return_value = default
return return_value
return return_value or default
class ChargeAttrShortcut(object):
def getModifiedChargeAttr(self, key, default=None):
def getModifiedChargeAttr(self, key, default=0):
return_value = self.chargeModifiedAttributes.get(key)
if return_value is None and default is not None:
return_value = default
return return_value
return return_value or default
class ModifiedAttributeDict(collections.MutableMapping):
@@ -165,9 +159,9 @@ class ModifiedAttributeDict(collections.MutableMapping):
def __len__(self):
keys = set()
keys.update(self.original.iterkeys())
keys.update(self.__modified.iterkeys())
keys.update(self.__intermediary.iterkeys())
keys.update(iter(self.original.keys()))
keys.update(iter(self.__modified.keys()))
keys.update(iter(self.__intermediary.keys()))
return len(keys)
def __calculateValue(self, key):
@@ -231,11 +225,11 @@ class ModifiedAttributeDict(collections.MutableMapping):
val *= multiplier
# Each group is penalized independently
# Things in different groups will not be stack penalized between each other
for penalizedMultipliers in penalizedMultiplierGroups.itervalues():
for penalizedMultipliers in penalizedMultiplierGroups.values():
# 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 = [_val for _val in penalizedMultipliers if _val > 1]
l2 = [_val for _val in penalizedMultipliers if _val < 1]
# 2: The most significant bonuses take the smallest penalty,
# This means we'll have to sort
abssort = lambda _val: -abs(_val - 1)
@@ -245,7 +239,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
# Any module after the first takes penalties according to:
# 1 + (multiplier - 1) * math.exp(- math.pow(i, 2) / 7.1289)
for l in (l1, l2):
for i in xrange(len(l)):
for i in range(len(l)):
bonus = l[i]
val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
val += postIncrease
@@ -388,7 +382,7 @@ class ModifiedAttributeDict(collections.MutableMapping):
"""Force value to attribute and prohibit any changes to it"""
self.__forced[attributeName] = value
self.__placehold(attributeName)
self.__afflict(attributeName, u"\u2263", value)
self.__afflict(attributeName, "\u2263", value)
@staticmethod
def getResistance(fit, effect):

View File

@@ -116,7 +116,7 @@ class Booster(HandledItem, ItemAttrShortcut):
if not self.active:
return
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
(effect.isType("passive") or effect.isType("boosterSideEffect")):
if effect.isType("boosterSideEffect") and effect not in self.activeSideEffectEffects:

View File

@@ -39,7 +39,7 @@ class BoosterSideEffect(object):
self.__effect = None
if self.effectID:
self.__effect = next((x for x in self.booster.item.effects.itervalues() if x.ID == self.effectID), None)
self.__effect = next((x for x in self.booster.item.effects.values() if x.ID == self.effectID), None)
if self.__effect is None:
pyfalog.error("Effect (id: {0}) does not exist", self.effectID)
return

View File

@@ -77,8 +77,8 @@ class Cargo(HandledItem, ItemAttrShortcut):
"amount": lambda _val: isinstance(_val, int)
}
if key == "amount" and val > sys.maxint:
val = sys.maxint
if key == "amount" and val > sys.maxsize:
val = sys.maxsize
if not map[key](val):
raise ValueError(str(val) + " is not a valid value for " + key)

View File

@@ -52,7 +52,6 @@ class Character(object):
self.addSkill(Skill(self, item.ID, self.defaultLevel))
self.__implants = HandledImplantBoosterList()
self.apiKey = None
@reconstructor
def init(self):
@@ -119,16 +118,9 @@ class Character(object):
return all0
def apiUpdateCharSheet(self, skills, secStatus=0):
for skillRow in skills:
try:
skill = self.getSkill(int(skillRow["typeID"]))
skill.setLevel(int(skillRow["level"]), persist=True, ignoreRestrict=True)
except:
# if setting a skill doesn't work, it's not the end of the world, just quietly pass
pass
self.secStatus = secStatus
def clearSkills(self):
del self.__skills[:]
self.__skillIdMap.clear()
@property
def ro(self):
@@ -162,7 +154,7 @@ class Character(object):
name += " *"
if self.alphaCloneID:
name += u' (\u03B1)'
name += ' (\u03B1)'
return name
@@ -170,6 +162,18 @@ class Character(object):
def name(self, name):
self.savedName = name
def setSsoCharacter(self, character, clientHash):
if character is not None:
self.__ssoCharacters.append(character)
else:
for x in self.__ssoCharacters:
if x.client == clientHash:
self.__ssoCharacters.remove(x)
def getSsoCharacter(self, clientHash):
return next((x for x in self.__ssoCharacters if x.client == clientHash), None)
@property
def alphaCloneID(self):
return self.__alphaCloneID
@@ -199,7 +203,7 @@ class Character(object):
del self.__skillIdMap[skill.itemID]
def getSkill(self, item):
if isinstance(item, basestring):
if isinstance(item, str):
item = self.getSkillNameMap()[item]
elif isinstance(item, int):
item = self.getSkillIDMap()[item]
@@ -269,20 +273,17 @@ class Character(object):
def __deepcopy__(self, memo):
copy = Character("%s copy" % self.name, initSkills=False)
copy.apiKey = self.apiKey
copy.apiID = self.apiID
for skill in self.skills:
copy.addSkill(Skill(copy, skill.itemID, skill.level, False, skill.learned))
return copy
@validates("ID", "name", "apiKey", "ownerID")
@validates("ID", "name", "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
}
@@ -344,13 +345,13 @@ class Skill(HandledItem):
elif self.character.name == "All 0":
self.activeLevel = self.__level = 0
elif self.character.alphaClone:
return min(self.activeLevel, self.character.alphaClone.getSkillLevel(self)) or 0
return min(self.activeLevel or 0, self.character.alphaClone.getSkillLevel(self) or 0)
return self.activeLevel or 0
def setLevel(self, level, persist=False, ignoreRestrict=False):
if (level < 0 or level > 5) and level is not None:
if level is not None and (level < 0 or level > 5):
raise ValueError(str(level) + " is not a valid value for level")
if hasattr(self, "_Skill__ro") and self.__ro is True:
@@ -362,9 +363,9 @@ class Skill(HandledItem):
# which affects performance. Should have a checkSkillLevels() or something that is more efficient for bulk.
if not ignoreRestrict and eos.config.settings['strictSkillLevels']:
start = time.time()
for item, rlevel in self.item.requiredFor.iteritems():
for item, rlevel in self.item.requiredFor.items():
if item.group.category.ID == 16: # Skill category
if level < rlevel:
if level is None or level < rlevel:
skill = self.character.getSkill(item.ID)
# print "Removing skill: {}, Dependant level: {}, Required level: {}".format(skill, level, rlevel)
skill.setLevel(None, persist)
@@ -392,7 +393,7 @@ class Skill(HandledItem):
if key in self.item.attributes:
return self.item.attributes[key].value
else:
return None
return 0
def calculateModifiedAttributes(self, fit, runTime):
if self.__suppressed: # or not self.learned - removed for GH issue 101
@@ -402,7 +403,7 @@ class Skill(HandledItem):
if item is None:
return
for effect in item.effects.itervalues():
for effect in item.effects.values():
if effect.runTime == runTime and \
effect.isType("passive") and \
(not fit.isStructure or effect.isType("structure")) and \

View File

@@ -73,7 +73,8 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.__itemModifiedAttributes.overrides = self.__item.overrides
self.__chargeModifiedAttributes = ModifiedAttributeDict()
chargeID = self.getModifiedItemAttr("entityMissileTypeID")
# pheonix todo: check the attribute itself, not the modified. this will always return 0 now.
chargeID = self.getModifiedItemAttr("entityMissileTypeID", None)
if chargeID is not None:
charge = eos.db.getItem(int(chargeID))
self.__charge = charge
@@ -102,7 +103,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@property
def cycleTime(self):
return max(self.getModifiedItemAttr("duration"), 0)
return max(self.getModifiedItemAttr("duration", 0), 0)
@property
def dealsDamage(self):
@@ -138,8 +139,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
cycleTime = self.getModifiedItemAttr(attr)
volley = sum(
map(lambda d: (getter("%sDamage" % d) or 0) * (1 - getattr(targetResists, "%sAmount" % d, 0)),
self.DAMAGE_TYPES))
[(getter("%sDamage" % d) or 0) * (1 - getattr(targetResists, "%sAmount" % d, 0)) for d in self.DAMAGE_TYPES])
volley *= self.amountActive
volley *= self.getModifiedItemAttr("damageMultiplier") or 1
self.__volley = volley
@@ -155,7 +155,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
getter = self.getModifiedItemAttr
cycleTime = self.getModifiedItemAttr(attr)
volley = sum(map(lambda d: getter(d), self.MINING_ATTRIBUTES)) * self.amountActive
volley = sum([getter(d) for d in self.MINING_ATTRIBUTES]) * self.amountActive
self.__miningyield = volley / (cycleTime / 1000.0)
else:
self.__miningyield = 0
@@ -168,7 +168,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"energyDestabilizationRange", "empFieldRange",
"ecmBurstRange", "maxRange")
for attr in attrs:
maxRange = self.getModifiedItemAttr(attr)
maxRange = self.getModifiedItemAttr(attr, None)
if maxRange is not None:
return maxRange
if self.charge is not None:
@@ -184,7 +184,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def falloff(self):
attrs = ("falloff", "falloffEffectiveness")
for attr in attrs:
falloff = self.getModifiedItemAttr(attr)
falloff = self.getModifiedItemAttr(attr, None)
if falloff is not None:
return falloff
@@ -236,7 +236,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
context = ("drone",)
projected = False
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.activeByDefault and \
((projected is True and effect.isType("projected")) or
@@ -251,7 +251,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
i += 1
if self.charge:
for effect in self.charge.effects.itervalues():
for effect in self.charge.effects.values():
if effect.runTime == runTime and effect.activeByDefault:
effect.handler(fit, self, ("droneCharge",))
@@ -263,8 +263,8 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def fits(self, fit):
fitDroneGroupLimits = set()
for i in xrange(1, 3):
groneGrp = fit.ship.getModifiedItemAttr("allowedDroneGroup%d" % i)
for i in range(1, 3):
groneGrp = fit.ship.getModifiedItemAttr("allowedDroneGroup%d" % i, None)
if groneGrp is not None:
fitDroneGroupLimits.add(int(groneGrp))
if len(fitDroneGroupLimits) == 0:

View File

@@ -98,7 +98,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def __getAbilities(self):
"""Returns list of FighterAbilities that are loaded with data"""
return [FighterAbility(effect) for effect in self.item.effects.values()]
return [FighterAbility(effect) for effect in list(self.item.effects.values())]
def __calculateSlot(self, item):
types = {
@@ -110,7 +110,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"StandupHeavy": Slot.FS_HEAVY
}
for t, slot in types.iteritems():
for t, slot in types.items():
if self.getModifiedItemAttr("fighterSquadronIs{}".format(t)):
return slot
@@ -202,12 +202,12 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"energyDestabilizationRange", "empFieldRange",
"ecmBurstRange", "maxRange")
for attr in attrs:
maxRange = self.getModifiedItemAttr(attr)
maxRange = self.getModifiedItemAttr(attr, None)
if maxRange is not None:
return maxRange
if self.charge is not None:
delay = self.getModifiedChargeAttr("explosionDelay")
speed = self.getModifiedChargeAttr("maxVelocity")
delay = self.getModifiedChargeAttr("explosionDelay", None)
speed = self.getModifiedChargeAttr("maxVelocity", None)
if delay is not None and speed is not None:
return delay / 1000.0 * speed
@@ -218,7 +218,7 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def falloff(self):
attrs = ("falloff", "falloffEffectiveness")
for attr in attrs:
falloff = self.getModifiedItemAttr(attr)
falloff = self.getModifiedItemAttr(attr, None)
if falloff is not None:
return falloff

View File

@@ -57,7 +57,7 @@ class FighterAbility(object):
self.__effect = None
if self.effectID:
self.__effect = next((x for x in self.fighter.item.effects.itervalues() if x.ID == self.effectID), None)
self.__effect = next((x for x in self.fighter.item.effects.values() if x.ID == self.effectID), None)
if self.__effect is None:
pyfalog.error("Effect (id: {0}) does not exist", self.effectID)
return
@@ -127,8 +127,8 @@ class FighterAbility(object):
if self.attrPrefix == "fighterAbilityLaunchBomb":
# bomb calcs
volley = sum(map(lambda attr: (self.fighter.getModifiedChargeAttr("%sDamage" % attr) or 0) * (
1 - getattr(targetResists, "%sAmount" % attr, 0)), self.DAMAGE_TYPES))
volley = sum([(self.fighter.getModifiedChargeAttr("%sDamage" % attr) or 0) * (
1 - getattr(targetResists, "%sAmount" % attr, 0)) for attr in self.DAMAGE_TYPES])
else:
volley = sum(map(lambda d2, d:
(self.fighter.getModifiedItemAttr(

View File

@@ -258,11 +258,11 @@ class Fit(object):
def projectedFits(self):
# only in extreme edge cases will the fit be invalid, but to be sure do
# not return them.
return [fit for fit in self.__projectedFits.values() if not fit.isInvalid]
return [fit for fit in list(self.__projectedFits.values()) if not fit.isInvalid]
@property
def commandFits(self):
return [fit for fit in self.__commandFits.values() if not fit.isInvalid]
return [fit for fit in list(self.__commandFits.values()) if not fit.isInvalid]
def getProjectionInfo(self, fitID):
return self.projectedOnto.get(fitID, None)
@@ -492,7 +492,7 @@ class Fit(object):
def __runCommandBoosts(self, runTime="normal"):
pyfalog.debug("Applying gang boosts for {0}", repr(self))
for warfareBuffID in self.commandBonuses.keys():
for warfareBuffID in list(self.commandBonuses.keys()):
# Unpack all data required to run effect properly
effect_runTime, value, thing, effect = self.commandBonuses[warfareBuffID]
@@ -676,7 +676,7 @@ class Fit(object):
def __resetDependentCalcs(self):
self.calculated = False
for value in self.projectedOnto.values():
for value in list(self.projectedOnto.values()):
if value.victim_fit: # removing a self-projected fit causes victim fit to be None. @todo: look into why. :3
value.victim_fit.calculated = False
@@ -707,14 +707,14 @@ class Fit(object):
self.__resetDependentCalcs()
# For fits that are under local's Command, we do the same thing
for value in self.boostedOnto.values():
for value in list(self.boostedOnto.values()):
# apparently this is a thing that happens when removing a command fit from a fit and then switching to
# that command fit. Same as projected clears, figure out why.
if value.boosted_fit:
value.boosted_fit.__resetDependentCalcs()
if targetFit and type == CalcType.PROJECTED:
pyfalog.debug(u"Calculating projections from {0} to target {1}", repr(self), repr(targetFit))
pyfalog.debug("Calculating projections from {0} to target {1}", repr(self), repr(targetFit))
projectionInfo = self.getProjectionInfo(targetFit.ID)
# Start applying any command fits that we may have.
@@ -756,7 +756,7 @@ class Fit(object):
# Loop through our run times here. These determine which effects are run in which order.
for runTime in ("early", "normal", "late"):
pyfalog.debug("Run time: {0}", runTime)
# pyfalog.debug("Run time: {0}", runTime)
# Items that are unrestricted. These items are run on the local fit
# first and then projected onto the target fit it one is designated
u = [
@@ -795,7 +795,7 @@ class Fit(object):
# targetFit.register(item, origin=self)
item.calculateModifiedAttributes(targetFit, runTime, False, True)
pyfalog.debug("Command Bonuses: {}".format(self.commandBonuses))
# pyfalog.debug("Command Bonuses: {}".format(self.commandBonuses))
# If we are calculating our local or projected fit and have command bonuses, apply them
if type != CalcType.COMMAND and self.commandBonuses:
@@ -838,7 +838,7 @@ class Fit(object):
for item in c:
if item is not None:
# apply effects onto target fit x amount of times
for _ in xrange(projectionInfo.amount):
for _ in range(projectionInfo.amount):
targetFit.register(item, origin=self)
item.calculateModifiedAttributes(targetFit, runTime, True)
@@ -854,7 +854,7 @@ class Fit(object):
for slotType in (Slot.LOW, Slot.MED, Slot.HIGH, Slot.RIG, Slot.SUBSYSTEM, Slot.SERVICE):
amount = self.getSlotsFree(slotType, True)
if amount > 0:
for _ in xrange(int(amount)):
for _ in range(int(amount)):
self.modules.append(Module.buildEmpty(slotType))
if amount < 0:
@@ -870,7 +870,7 @@ class Fit(object):
self.modules.remove(mod)
def unfill(self):
for i in xrange(len(self.modules) - 1, -1, -1):
for i in range(len(self.modules) - 1, -1, -1):
mod = self.modules[i]
if mod.isEmpty:
del self.modules[i]
@@ -878,7 +878,7 @@ class Fit(object):
@property
def modCount(self):
x = 0
for i in xrange(len(self.modules) - 1, -1, -1):
for i in range(len(self.modules) - 1, -1, -1):
mod = self.modules[i]
if not mod.isEmpty:
x += 1
@@ -1143,14 +1143,16 @@ class Fit(object):
except AttributeError:
usesCap = False
cycleTime = mod.rawCycleTime
amount = mod.getModifiedItemAttr(groupAttrMap[mod.item.group.name])
# Normal Repairers
if usesCap and not mod.charge:
cycleTime = mod.rawCycleTime
amount = mod.getModifiedItemAttr(groupAttrMap[mod.item.group.name])
sustainable[attr] -= amount / (cycleTime / 1000.0)
repairers.append(mod)
# Ancillary Armor reps etc
elif usesCap and mod.charge:
cycleTime = mod.rawCycleTime
amount = mod.getModifiedItemAttr(groupAttrMap[mod.item.group.name])
if mod.charge.name == "Nanite Repair Paste":
multiplier = mod.getModifiedItemAttr("chargedArmorDamageMultiplier") or 1
else:
@@ -1158,7 +1160,9 @@ class Fit(object):
sustainable[attr] -= amount * multiplier / (cycleTime / 1000.0)
repairers.append(mod)
# Ancillary Shield boosters etc
elif not usesCap:
elif not usesCap and mod.item.group.name in ("Ancillary Shield Booster", "Ancillary Remote Shield Booster"):
cycleTime = mod.rawCycleTime
amount = mod.getModifiedItemAttr(groupAttrMap[mod.item.group.name])
if self.factorReload and mod.charge:
reloadtime = mod.reloadTime
else:
@@ -1527,11 +1531,11 @@ class Fit(object):
return copy_ship
def __repr__(self):
return u"Fit(ID={}, ship={}, name={}) at {}".format(
return "Fit(ID={}, ship={}, name={}) at {}".format(
self.ID, self.ship.item.name, self.name, hex(id(self))
).encode('utf8')
)
def __str__(self):
return u"{} ({})".format(
return "{} ({})".format(
self.name, self.ship.item.name
).encode('utf8')
)

View File

@@ -93,7 +93,7 @@ class Implant(HandledItem, ItemAttrShortcut):
return
if not self.active:
return
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and effect.isType("passive") and effect.activeByDefault:
effect.handler(fit, self, ("implant",))

View File

@@ -50,6 +50,6 @@ class Mode(ItemAttrShortcut, HandledItem):
def calculateModifiedAttributes(self, fit, runTime, forceProjected=False):
if self.item:
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and effect.activeByDefault:
effect.handler(fit, self, context=("module",))

View File

@@ -182,7 +182,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@property
def numShots(self):
if self.charge is None:
return None
return 0
if self.__chargeCycles is None and self.charge:
numCharges = self.numCharges
# Usual ammo like projectiles and missiles
@@ -217,7 +217,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
armorRep = self.getModifiedItemAttr("armorDamageAmount") or 0
shieldRep = self.getModifiedItemAttr("shieldBonus") or 0
if not cycles or (not armorRep and not shieldRep):
return None
return 0
hp = round((armorRep + shieldRep) * cycles)
return hp
@@ -255,7 +255,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"ecmBurstRange", "warpScrambleRange", "cargoScanRange",
"shipScanRange", "surveyScanRange")
for attr in attrs:
maxRange = self.getModifiedItemAttr(attr)
maxRange = self.getModifiedItemAttr(attr, None)
if maxRange is not None:
return maxRange
if self.charge is not None:
@@ -284,7 +284,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def falloff(self):
attrs = ("falloffEffectiveness", "falloff", "shipScanFalloff")
for attr in attrs:
falloff = self.getModifiedItemAttr(attr)
falloff = self.getModifiedItemAttr(attr, None)
if falloff is not None:
return falloff
@@ -333,9 +333,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
else:
func = self.getModifiedItemAttr
volley = sum(map(
lambda attr: (func("%sDamage" % attr) or 0) * (1 - getattr(targetResists, "%sAmount" % attr, 0)),
self.DAMAGE_TYPES))
volley = sum([(func("%sDamage" % attr) or 0) * (1 - getattr(targetResists, "%sAmount" % attr, 0)) for attr in self.DAMAGE_TYPES])
volley *= self.getModifiedItemAttr("damageMultiplier") or 1
# Disintegrator-specific ramp-up multiplier
volley *= (self.getModifiedItemAttr("damageMultiplierBonusMax") or 0) + 1
@@ -424,19 +422,19 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
fitsOnType = set()
fitsOnGroup = set()
shipType = self.getModifiedItemAttr("fitsToShipType")
shipType = self.getModifiedItemAttr("fitsToShipType", None)
if shipType is not None:
fitsOnType.add(shipType)
for attr in self.itemModifiedAttributes.keys():
for attr in list(self.itemModifiedAttributes.keys()):
if attr.startswith("canFitShipType"):
shipType = self.getModifiedItemAttr(attr)
shipType = self.getModifiedItemAttr(attr, None)
if shipType is not None:
fitsOnType.add(shipType)
for attr in self.itemModifiedAttributes.keys():
for attr in list(self.itemModifiedAttributes.keys()):
if attr.startswith("canFitShipGroup"):
shipGroup = self.getModifiedItemAttr(attr)
shipGroup = self.getModifiedItemAttr(attr, None)
if shipGroup is not None:
fitsOnGroup.add(shipGroup)
@@ -468,7 +466,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return False
# Check max group fitted
max = self.getModifiedItemAttr("maxGroupFitted")
max = self.getModifiedItemAttr("maxGroupFitted", None)
if max is not None:
current = 0 # if self.owner != fit else -1 # Disabled, see #1278
for mod in fit.modules:
@@ -481,11 +479,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
# Check this only if we're told to do so
if hardpointLimit:
if self.hardpoint == Hardpoint.TURRET:
if (fit.ship.getModifiedItemAttr('turretSlotsLeft') or 0) - fit.getHardpointsUsed(Hardpoint.TURRET) < 1:
if fit.ship.getModifiedItemAttr('turretSlotsLeft') - fit.getHardpointsUsed(Hardpoint.TURRET) < 1:
return False
elif self.hardpoint == Hardpoint.MISSILE:
if (fit.ship.getModifiedItemAttr('launcherSlotsLeft') or 0) - fit.getHardpointsUsed(
Hardpoint.MISSILE) < 1:
if fit.ship.getModifiedItemAttr('launcherSlotsLeft') - fit.getHardpointsUsed(Hardpoint.MISSILE) < 1:
return False
return True
@@ -515,7 +512,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return True
# Check if the local module is over it's max limit; if it's not, we're fine
maxGroupActive = self.getModifiedItemAttr("maxGroupActive")
maxGroupActive = self.getModifiedItemAttr("maxGroupActive", None)
if maxGroupActive is None and projectedOnto is None:
return True
@@ -563,7 +560,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
chargeGroup = charge.groupID
for i in range(5):
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i))
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i), None)
if itemChargeGroup is None:
continue
if itemChargeGroup == chargeGroup:
@@ -574,7 +571,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def getValidCharges(self):
validCharges = set()
for i in range(5):
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i))
itemChargeGroup = self.getModifiedItemAttr('chargeGroup' + str(i), None)
if itemChargeGroup is not None:
g = eos.db.getGroup(int(itemChargeGroup), eager=("items.icon", "items.attributes"))
if g is None:
@@ -595,7 +592,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if item is None:
return Hardpoint.NONE
for effectName, slot in effectHardpointMap.iteritems():
for effectName, slot in effectHardpointMap.items():
if effectName in item.effects:
return slot
@@ -613,7 +610,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
}
if item is None:
return None
for effectName, slot in effectSlotMap.iteritems():
for effectName, slot in effectSlotMap.items():
if effectName in item.effects:
return slot
if item.group.name == "Effect Beacon":
@@ -667,7 +664,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if self.charge is not None:
# fix for #82 and it's regression #106
if not projected or (self.projected and not forceProjected) or gang:
for effect in self.charge.effects.itervalues():
for effect in self.charge.effects.values():
if effect.runTime == runTime and \
effect.activeByDefault and \
(effect.isType("offline") or
@@ -686,7 +683,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if self.item:
if self.state >= State.OVERHEATED:
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.isType("overheat") \
and not forceProjected \
@@ -694,7 +691,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
and ((gang and effect.isType("gang")) or not gang):
effect.handler(fit, self, context)
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.activeByDefault and \
(effect.isType("offline") or
@@ -754,13 +751,12 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@property
def rawCycleTime(self):
speed = max(
self.getModifiedItemAttr("speed"), # Most weapons
self.getModifiedItemAttr("duration"), # Most average modules
self.getModifiedItemAttr("durationSensorDampeningBurstProjector"),
self.getModifiedItemAttr("durationTargetIlluminationBurstProjector"),
self.getModifiedItemAttr("durationECMJammerBurstProjector"),
self.getModifiedItemAttr("durationWeaponDisruptionBurstProjector"),
0, # Return 0 if none of the above are valid
self.getModifiedItemAttr("speed", 0), # Most weapons
self.getModifiedItemAttr("duration", 0), # Most average modules
self.getModifiedItemAttr("durationSensorDampeningBurstProjector", 0),
self.getModifiedItemAttr("durationTargetIlluminationBurstProjector", 0),
self.getModifiedItemAttr("durationECMJammerBurstProjector", 0),
self.getModifiedItemAttr("durationWeaponDisruptionBurstProjector", 0)
)
return speed
@@ -795,7 +791,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def __repr__(self):
if self.item:
return u"Module(ID={}, name={}) at {}".format(
return "Module(ID={}, name={}) at {}".format(
self.item.ID, self.item.name, hex(id(self))
)
else:

View File

@@ -87,7 +87,7 @@ class Ship(ItemAttrShortcut, HandledItem):
def calculateModifiedAttributes(self, fit, runTime, forceProjected=False):
if forceProjected:
return
for effect in self.item.effects.itervalues():
for effect in self.item.effects.values():
if effect.runTime == runTime and \
effect.isType("passive") and \
effect.activeByDefault:

View File

@@ -18,17 +18,32 @@
# ===============================================================================
from sqlalchemy.orm import reconstructor
import datetime
import time
# from tomorrow import threads
class CrestChar(object):
def __init__(self, id, name, refresh_token=None):
self.ID = id
self.name = name
self.refresh_token = refresh_token
class SsoCharacter(object):
def __init__(self, charID, name, client, accessToken=None, refreshToken=None):
self.characterID = charID
self.characterName = name
self.client = client
self.accessToken = accessToken
self.refreshToken = refreshToken
self.accessTokenExpires = None
@reconstructor
def init(self):
pass
def is_token_expired(self):
if self.accessTokenExpires is None:
return True
return datetime.datetime.now() >= self.accessTokenExpires
def __repr__(self):
return "SsoCharacter(ID={}, name={}, client={}) at {}".format(
self.ID, self.characterName, self.client, hex(id(self))
)

View File

@@ -33,7 +33,7 @@ class User(object):
def encodeAndSetPassword(self, pw):
h = hashlib.new("sha256")
salt = "".join([random.choice(string.letters) for _ in xrange(32)])
salt = "".join([random.choice(string.letters) for _ in range(32)])
h.update(pw)
h.update(salt)
self.password = ("%s%s" % (h.hexdigest(), salt))
@@ -45,14 +45,14 @@ class User(object):
h = hashlib.new("sha256")
h.update(pw)
h.update(salt)
return self.password == (u"%s%s" % (h.hexdigest(), salt))
return self.password == ("%s%s" % (h.hexdigest(), salt))
@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,
"username": lambda _val: isinstance(_val, str),
"password": lambda _val: isinstance(_val, str) and len(_val) == 96,
"admin" : lambda _val: isinstance(_val, bool)
}