Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/projections'
Browse files Browse the repository at this point in the history
  • Loading branch information
blitzmann committed Jul 23, 2015
2 parents 505b0ce + 2f246d0 commit e74e261
Show file tree
Hide file tree
Showing 18 changed files with 829 additions and 330 deletions.
32 changes: 23 additions & 9 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# Defines if our saveddata will be in pyfa root or not
saveInRoot = False

logLevel = logging.WARN
logLevel = logging.DEBUG

# Version data
version = "1.13.3"
Expand All @@ -32,6 +32,21 @@
saveDB = None
gameDB = None


class StreamToLogger(object):
"""
Fake file-like stream object that redirects writes to a logger instance.
From: http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/
"""
def __init__(self, logger, log_level=logging.INFO):
self.logger = logger
self.log_level = log_level
self.linebuf = ''

def write(self, buf):
for line in buf.rstrip().splitlines():
self.logger.log(self.log_level, line.rstrip())

def __createDirs(path):
if not os.path.exists(path):
os.makedirs(path)
Expand Down Expand Up @@ -72,15 +87,14 @@ def defPaths():

logging.info("Starting pyfa")

# Redirect stderr to file if we're requested to do so
stderrToFile = getattr(configforced, "stderrToFile", None)
if stderrToFile is True:
sys.stderr = open(os.path.join(savePath, "error_log.txt"), "w")
if hasattr(sys, 'frozen'):
stdout_logger = logging.getLogger('STDOUT')
sl = StreamToLogger(stdout_logger, logging.INFO)
sys.stdout = sl

# Same for stdout
stdoutToFile = getattr(configforced, "stdoutToFile", None)
if stdoutToFile is True:
sys.stdout = open(os.path.join(savePath, "output_log.txt"), "w")
stderr_logger = logging.getLogger('STDERR')
sl = StreamToLogger(stderr_logger, logging.ERROR)
sys.stderr = sl

# Static EVE Data from the staticdata repository, should be in the staticdata
# directory in our pyfa directory
Expand Down
16 changes: 16 additions & 0 deletions eos/db/migrations/upgrade10.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Migration 10
- Adds active attribute to projected fits
"""

import sqlalchemy

def upgrade(saveddata_engine):
# Update projectedFits schema to include active attribute
try:
saveddata_engine.execute("SELECT active FROM projectedFits LIMIT 1")
except sqlalchemy.exc.DatabaseError:
saveddata_engine.execute("ALTER TABLE projectedFits ADD COLUMN active BOOLEAN")
saveddata_engine.execute("UPDATE projectedFits SET active = 1")
saveddata_engine.execute("UPDATE projectedFits SET amount = 1")
150 changes: 119 additions & 31 deletions eos/db/saveddata/fit.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================

from sqlalchemy import Table, Column, Integer, ForeignKey, String, Boolean
from sqlalchemy.orm import relation, mapper
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.sql import and_
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm.collections import attribute_mapped_collection

from eos.db import saveddata_meta
from eos.db.saveddata.module import modules_table
Expand All @@ -45,33 +47,119 @@
projectedFits_table = Table("projectedFits", saveddata_meta,
Column("sourceID", ForeignKey("fits.ID"), primary_key = True),
Column("victimID", ForeignKey("fits.ID"), primary_key = True),
Column("amount", Integer))
Column("amount", Integer, nullable = False, default = 1),
Column("active", Boolean, nullable = False, default = 1),
)

class ProjectedFit(object):
def __init__(self, sourceID, source_fit, amount=1, active=True):
self.sourceID = sourceID
self.source_fit = source_fit
self.active = active
self.__amount = amount

@reconstructor
def init(self):
if self.source_fit.isInvalid:
# Very rare for this to happen, but be prepared for it
eos.db.saveddata_session.delete(self.source_fit)
eos.db.saveddata_session.flush()
eos.db.saveddata_session.refresh(self.victim_fit)

# We have a series of setters and getters here just in case someone
# downgrades and screws up the table with NULL values
@property
def amount(self):
return self.__amount or 1

@amount.setter
def amount(self, amount):
self.__amount = amount

def __repr__(self):
return "ProjectedFit(sourceID={}, victimID={}, amount={}, active={}) at {}".format(
self.sourceID, self.victimID, self.amount, self.active, hex(id(self))
)

Fit._Fit__projectedFits = association_proxy(
"victimOf", # look at the victimOf association...
"source_fit", # .. and return the source fits
creator=lambda sourceID, source_fit: ProjectedFit(sourceID, source_fit)
)

mapper(Fit, fits_table,
properties = {"_Fit__modules" : relation(Module, collection_class = HandledModuleList,
primaryjoin = and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
order_by = modules_table.c.position, cascade='all, delete, delete-orphan'),
"_Fit__projectedModules" : relation(Module, 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)),
"owner" : relation(User, backref = "fits"),
"itemID" : fits_table.c.shipID,
"shipID" : fits_table.c.shipID,
"_Fit__boosters" : relation(Booster, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', single_parent=True),
"_Fit__drones" : relation(Drone, 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)),
"_Fit__cargo" : relation(Cargo, collection_class = HandledDroneCargoList, cascade='all, delete, delete-orphan', single_parent=True,
primaryjoin = and_(cargo_table.c.fitID == fits_table.c.ID)),
"_Fit__projectedDrones" : relation(Drone, 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)),
"_Fit__implants" : relation(Implant, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', backref='fit', single_parent=True,
primaryjoin = fitImplants_table.c.fitID == fits_table.c.ID,
secondaryjoin = fitImplants_table.c.implantID == Implant.ID,
secondary = fitImplants_table),
"_Fit__character" : relation(Character, backref = "fits"),
"_Fit__damagePattern" : relation(DamagePattern),
"_Fit__targetResists" : relation(TargetResists),
"_Fit__projectedFits" : relation(Fit,
primaryjoin = projectedFits_table.c.victimID == fits_table.c.ID,
secondaryjoin = fits_table.c.ID == projectedFits_table.c.sourceID,
secondary = projectedFits_table,
collection_class = HandledProjectedFitList)
})
properties = {
"_Fit__modules": relation(
Module,
collection_class=HandledModuleList,
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
order_by=modules_table.c.position,
cascade='all, delete, delete-orphan'),
"_Fit__projectedModules": relation(
Module,
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)),
"owner": relation(
User,
backref="fits"),
"itemID": fits_table.c.shipID,
"shipID": fits_table.c.shipID,
"_Fit__boosters": relation(
Booster,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
single_parent=True),
"_Fit__drones": relation(
Drone,
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)),
"_Fit__cargo": relation(
Cargo,
collection_class=HandledDroneCargoList,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
"_Fit__projectedDrones": relation(
Drone,
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)),
"_Fit__implants": relation(
Implant,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
backref='fit',
single_parent=True,
primaryjoin=fitImplants_table.c.fitID == fits_table.c.ID,
secondaryjoin=fitImplants_table.c.implantID == Implant.ID,
secondary=fitImplants_table),
"_Fit__character": relation(
Character,
backref="fits"),
"_Fit__damagePattern": relation(DamagePattern),
"_Fit__targetResists": relation(TargetResists),
"projectedOnto": relationship(
ProjectedFit,
primaryjoin=projectedFits_table.c.sourceID == fits_table.c.ID,
backref='source_fit',
collection_class=attribute_mapped_collection('victimID'),
cascade='all, delete, delete-orphan'),
"victimOf": relationship(
ProjectedFit,
primaryjoin=fits_table.c.ID == projectedFits_table.c.victimID,
backref='victim_fit',
collection_class=attribute_mapped_collection('sourceID'),
cascade='all, delete, delete-orphan'),
}
)

mapper(ProjectedFit, projectedFits_table,
properties = {
"_ProjectedFit__amount": projectedFits_table.c.amount,
}
)
5 changes: 0 additions & 5 deletions eos/effectHandlerHelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,6 @@ def append(self, proj):
if proj.isInvalid or not proj.item.isType("projected"):
self.remove(proj)

class HandledProjectedFitList(HandledList):
def append(self, proj):
proj.projected = True
list.append(self, proj)

class HandledItem(object):
def preAssignItemAttr(self, *args, **kwargs):
self.itemModifiedAttributes.preAssign(*args, **kwargs)
Expand Down
9 changes: 6 additions & 3 deletions eos/modifiedAttributeDict.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,16 @@ def __afflict(self, attributeName, operation, bonus, used=True):
if attributeName not in self.__affectedBy:
self.__affectedBy[attributeName] = {}
affs = self.__affectedBy[attributeName]
origin = self.fit.getOrigin()
fit = origin if origin and origin != self.fit else self.fit
# If there's no set for current fit in dictionary, create it
if self.fit not in affs:
affs[self.fit] = []
if fit not in affs:
affs[fit] = []
# Reassign alias to list
affs = affs[self.fit]
affs = affs[fit]
# Get modifier which helps to compose 'Affected by' map
modifier = self.fit.getModifier()

# Add current affliction to list
affs.append((modifier, operation, bonus, used))

Expand Down
5 changes: 5 additions & 0 deletions eos/saveddata/character.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,5 +286,10 @@ def __deepcopy__(self, memo):
copy = Skill(self.item, self.level, self.__ro)
return copy

def __repr__(self):
return "Skill(ID={}, name={}) at {}".format(
self.item.ID, self.item.name, hex(id(self))
)

class ReadOnlyException(Exception):
pass
Loading

0 comments on commit e74e261

Please sign in to comment.