Merge branch 'feature/recent' into dev

Conflicts:
	eos/db/saveddata/character.py
	eos/db/saveddata/fit.py

Implements #983 but utilizing sqlalchemy events to update the fit modified date whenever something is added/changed.
This commit is contained in:
blitzmann
2017-05-07 20:48:41 -04:00
23 changed files with 356 additions and 103 deletions

View File

@@ -27,12 +27,11 @@ from eos.db.gamedata.group import groups_table
from eos.db.util import processEager, processWhere
from eos.gamedata import AlphaClone, Attribute, Category, Group, Item, MarketGroup, MetaGroup, AttributeInfo, MetaData
cache = {}
configVal = getattr(eos.config, "gamedataCache", None)
if configVal is True:
def cachedQuery(amount, *keywords):
def deco(function):
cache = {}
def checkAndReturn(*args, **kwargs):
useCache = kwargs.pop("useCache", True)
cacheKey = []
@@ -98,6 +97,34 @@ def getItem(lookfor, eager=None):
return item
@cachedQuery(1, "lookfor")
def getItems(lookfor, eager=None):
"""
Gets a list of items. Does a bit of cache hackery to get working properly -- cache
is usually based on function calls with the parameters, needed to extract data directly.
Works well enough. Not currently used, but it's here for possible future inclusion
"""
toGet = []
results = []
for id in lookfor:
if (id, None) in cache:
results.append(cache.get((id, None)))
else:
toGet.append(id)
if len(toGet) > 0:
# Get items that aren't currently cached, and store them in the cache
items = gamedata_session.query(Item).filter(Item.ID.in_(toGet)).all()
for item in items:
cache[(item.ID, None)] = item
results += items
# sort the results based on the original indexing
results.sort(key=lambda x: lookfor.index(x.ID))
return results
@cachedQuery(1, "lookfor")
def getAlphaClone(lookfor, eager=None):
if isinstance(lookfor, int):

View File

@@ -20,7 +20,7 @@
from sqlalchemy import Table, Column, ForeignKey, Integer, Boolean, DateTime
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import mapper, relation
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.booster import Booster
@@ -30,8 +30,8 @@ boosters_table = Table("boosters", saveddata_meta,
Column("itemID", Integer),
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False),
Column("active", Boolean),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now()),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
)
# Legacy booster side effect code, should disable but a mapper relies on it.

View File

@@ -18,19 +18,24 @@
# ===============================================================================
from sqlalchemy import Table, Column, Integer, ForeignKey, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
from sqlalchemy.orm import mapper, relation
import datetime
from eos.db import saveddata_meta
from eos.saveddata.cargo import Cargo
from eos.saveddata.fit import Fit
cargo_table = Table("cargo", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
Column("itemID", Integer, nullable=False),
Column("amount", Integer, nullable=False),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now()),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
)
mapper(Cargo, cargo_table)
mapper(Cargo, cargo_table,
properties={
"owner": relation(Fit)
}
)

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Float
from sqlalchemy.orm import relation, mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.db.saveddata.implant import charImplants_table
@@ -39,8 +39,8 @@ characters_table = Table("characters", saveddata_meta,
Column("alphaCloneID", Integer, nullable=True),
Column("ownerID", ForeignKey("users.ID"), nullable=True),
Column("secStatus", Float, nullable=True, default=0.0),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now()))
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now))
mapper(Character, characters_table,
properties={

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, String, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.crestchar import CrestChar
@@ -29,6 +29,6 @@ crest_table = Table("crest", saveddata_meta,
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=func.now()))
Column("created", DateTime, nullable=True, default=datetime.datetime.now))
mapper(CrestChar, crest_table)

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.damagePattern import DamagePattern
@@ -32,8 +32,8 @@ damagePatterns_table = Table("damagePatterns", saveddata_meta,
Column("kineticAmount", Integer),
Column("explosiveAmount", Integer),
Column("ownerID", ForeignKey("users.ID"), nullable=True),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
mapper(DamagePattern, damagePatterns_table)

View File

@@ -18,11 +18,12 @@
# ===============================================================================
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
from sqlalchemy.orm import mapper, relation
import datetime
from eos.db import saveddata_meta
from eos.saveddata.drone import Drone
from eos.saveddata.fit import Fit
drones_table = Table("drones", saveddata_meta,
Column("groupID", Integer, primary_key=True),
@@ -31,8 +32,12 @@ drones_table = Table("drones", saveddata_meta,
Column("amount", Integer, nullable=False),
Column("amountActive", Integer, nullable=False),
Column("projected", Boolean, default=False),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
mapper(Drone, drones_table)
mapper(Drone, drones_table,
properties={
"owner": relation(Fit)
}
)

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean, DateTime
from sqlalchemy.orm import mapper, relation
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.fighterAbility import FighterAbility
@@ -33,8 +33,8 @@ fighters_table = Table("fighters", saveddata_meta,
Column("active", Boolean, nullable=True),
Column("amount", Integer, nullable=False),
Column("projected", Boolean, default=False),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
fighter_abilities_table = Table("fightersAbilities", saveddata_meta,

View File

@@ -22,7 +22,7 @@ from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.sql import and_
from sqlalchemy.orm import relation, reconstructor, mapper, relationship
from sqlalchemy import ForeignKey, Column, Integer, String, Table, Boolean, DateTime
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.db import saveddata_session
@@ -59,8 +59,8 @@ fits_table = Table("fits", saveddata_meta,
Column("implantLocation", Integer, nullable=False, default=ImplantLocation.FIT),
Column("notes", String, nullable=True),
Column("ignoreRestrictions", Boolean, default=0),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, default=datetime.datetime.now, onupdate=datetime.datetime.now)
)
projectedFits_table = Table("projectedFits", saveddata_meta,
@@ -68,16 +68,16 @@ projectedFits_table = Table("projectedFits", saveddata_meta,
Column("victimID", ForeignKey("fits.ID"), primary_key=True),
Column("amount", Integer, nullable=False, default=1),
Column("active", Boolean, nullable=False, default=1),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
commandFits_table = Table("commandFits", saveddata_meta,
Column("boosterID", ForeignKey("fits.ID"), primary_key=True),
Column("boostedID", ForeignKey("fits.ID"), primary_key=True),
Column("active", Boolean, nullable=False, default=1),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
@@ -143,49 +143,70 @@ es_Fit._Fit__commandFits = association_proxy(
"booster_fit", # .. and return the booster fit
creator=lambda boosterID, booster_fit: CommandFit(boosterID, booster_fit)
)
# These relationships are broken out so that we can easily access it in the events stuff
# We sometimes don't want particular relationships to cause a fit modified update (eg: projecting
# a fit onto another would 'modify' both fits unless the following relationship is ignored)
projectedFitSourceRel = 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')
boostedOntoRel = relationship(
CommandFit,
primaryjoin=commandFits_table.c.boosterID == fits_table.c.ID,
backref='booster_fit',
collection_class=attribute_mapped_collection('boostedID'),
cascade='all, delete, delete-orphan')
mapper(es_Fit, fits_table,
properties={
"_Fit__modules" : relation(
"_Fit__modules": relation(
Module,
collection_class=HandledModuleList,
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(
"_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)), # noqa
"owner" : relation(
"owner": relation(
User,
backref="fits"),
"itemID" : fits_table.c.shipID,
"shipID" : fits_table.c.shipID,
"_Fit__boosters" : relation(
"itemID": fits_table.c.shipID,
"shipID": fits_table.c.shipID,
"_Fit__boosters": relation(
Booster,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
backref='owner',
single_parent=True),
"_Fit__drones" : relation(
"_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)), # noqa
"_Fit__fighters" : relation(
"_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
"_Fit__cargo" : relation(
"_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(
"_Fit__projectedDrones": relation(
Drone,
collection_class=HandledProjectedDroneList,
cascade='all, delete, delete-orphan',
@@ -197,51 +218,41 @@ mapper(es_Fit, fits_table,
cascade='all, delete, delete-orphan',
single_parent=True,
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
"_Fit__implants" : relation(
"_Fit__implants": relation(
Implant,
collection_class=HandledImplantBoosterList,
cascade='all, delete, delete-orphan',
backref='fit',
backref='owner',
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(
"_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(
"_Fit__damagePattern": relation(DamagePattern),
"_Fit__targetResists": relation(TargetResists),
"projectedOnto": projectedFitSourceRel,
"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'),
"boostedOnto" : relationship(
CommandFit,
primaryjoin=commandFits_table.c.boosterID == fits_table.c.ID,
backref='booster_fit',
collection_class=attribute_mapped_collection('boostedID'),
cascade='all, delete, delete-orphan'),
"boostedOf" : relationship(
"boostedOnto": boostedOntoRel,
"boostedOf": relationship(
CommandFit,
primaryjoin=fits_table.c.ID == commandFits_table.c.boostedID,
backref='boosted_fit',
collection_class=attribute_mapped_collection('boosterID'),
cascade='all, delete, delete-orphan'),
}
)
)
mapper(ProjectedFit, projectedFits_table,
properties={
"_ProjectedFit__amount": projectedFits_table.c.amount,
}
)
)
mapper(CommandFit, commandFits_table)

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.implant import Implant
@@ -28,8 +28,8 @@ implants_table = Table("implants", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("itemID", Integer),
Column("active", Boolean),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
fitImplants_table = Table("fitImplants", saveddata_meta,

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, String, DateTime
from sqlalchemy.orm import relation, mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.db.saveddata.implant import implantsSetMap_table
@@ -30,8 +30,8 @@ from eos.saveddata.implantSet import ImplantSet
implant_set_table = Table("implantSets", saveddata_meta,
Column("ID", Integer, primary_key=True),
Column("name", String, nullable=False),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
mapper(ImplantSet, implant_set_table,

View File

@@ -17,9 +17,9 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Boolean, DateTime
from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Boolean, DateTime, select
from sqlalchemy.orm import relation, mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.module import Module
@@ -34,9 +34,12 @@ modules_table = Table("modules", saveddata_meta,
Column("state", Integer, CheckConstraint("state >= -1"), CheckConstraint("state <= 2")),
Column("projected", Boolean, default=False, nullable=False),
Column("position", Integer),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now()),
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now),
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
mapper(Module, modules_table,
properties={"owner": relation(Fit)})

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, Float, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.override import Override
@@ -28,8 +28,8 @@ overrides_table = Table("overrides", saveddata_meta,
Column("itemID", Integer, primary_key=True, index=True),
Column("attrID", Integer, primary_key=True, index=True),
Column("value", Float, nullable=False),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
mapper(Override, overrides_table)

View File

@@ -18,6 +18,7 @@
# ===============================================================================
from sqlalchemy.sql import and_
from sqlalchemy import desc, select
from eos.db import saveddata_session, sd_lock
from eos.db.saveddata.fit import projectedFits_table
@@ -242,6 +243,22 @@ def getFitsWithShip(shipID, ownerID=None, where=None, eager=None):
return fits
def getRecentFits(ownerID=None, where=None, eager=None):
eager = processEager(eager)
with sd_lock:
q = select((
Fit.ID,
Fit.shipID,
Fit.name,
Fit.modified,
Fit.created,
Fit.timestamp
)).order_by(desc(Fit.modified), desc(Fit.timestamp)).limit(50)
fits = eos.db.saveddata_session.execute(q).fetchall()
return fits
def getFitsWithModules(typeIDs, eager=None):
"""
Get all the fits that have typeIDs fitted to them

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, ForeignKey, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.character import Skill
@@ -29,8 +29,8 @@ skills_table = Table("characterSkills", saveddata_meta,
Column("characterID", ForeignKey("characters.ID"), primary_key=True, index=True),
Column("itemID", Integer, primary_key=True),
Column("_Skill__level", Integer, nullable=True),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
mapper(Skill, skills_table)

View File

@@ -19,7 +19,7 @@
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, String, DateTime
from sqlalchemy.orm import mapper
import sqlalchemy.sql.functions as func
import datetime
from eos.db import saveddata_meta
from eos.saveddata.targetResists import TargetResists
@@ -32,8 +32,8 @@ targetResists_table = Table("targetResists", saveddata_meta,
Column("kineticAmount", Float),
Column("explosiveAmount", Float),
Column("ownerID", ForeignKey("users.ID"), nullable=True),
Column("created", DateTime, nullable=True, default=func.now()),
Column("modified", DateTime, nullable=True, onupdate=func.now())
Column("created", DateTime, nullable=True, default=datetime.datetime.now),
Column("modified", DateTime, nullable=True, onupdate=datetime.datetime.now)
)
mapper(TargetResists, targetResists_table)

86
eos/events.py Normal file
View File

@@ -0,0 +1,86 @@
# Decided to put this in it's own file so that we can easily choose not to import it (thanks to mac-deprecated builds =/)
import datetime
from sqlalchemy.event import listen
from sqlalchemy.orm.collections import InstrumentedList
from eos.db.saveddata.fit import projectedFitSourceRel, boostedOntoRel
from eos.saveddata.fit import Fit
from eos.saveddata.module import Module
from eos.saveddata.drone import Drone
from eos.saveddata.fighter import Fighter
from eos.saveddata.cargo import Cargo
from eos.saveddata.implant import Implant
from eos.saveddata.booster import Booster
ignored_rels = [
projectedFitSourceRel,
boostedOntoRel
]
def update_fit_modified(target, value, oldvalue, initiator):
if not target.owner:
return
if value != oldvalue:
# some things (like Implants) have a backref to the fit, which actually produces a list.
# In this situation, simply take the 0 index to get to the fit.
# There may be cases in the future in which there are multiple fits, so this should be
# looked at more indepth later
if isinstance(target.owner, InstrumentedList):
parent = target.owner[0]
else:
parent = target.owner
# ensure this is a fit we're dealing with
if isinstance(parent, Fit):
parent.modified = datetime.datetime.now()
def apply_col_listeners(target, context):
# We only want to set these events when the module is first loaded (otherwise events will fire during the initial
# population of data). This runs through all columns and sets up "set" events on each column. We do it with each
# column because the alternative would be to do a before/after_update for the Mapper itself, however we're only
# allowed to change the local attributes during those events as that's inter-flush.
# See http://docs.sqlalchemy.org/en/rel_1_0/orm/session_events.html#mapper-level-events
# @todo replace with `inspect(Module).column_attrs` when mac binaries are updated
manager = getattr(target.__class__, "_sa_class_manager", None)
if manager:
for col in manager.mapper.column_attrs:
listen(col, 'set', update_fit_modified)
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)
target.modified = datetime.datetime.now()
def apply_rel_listeners(target, context):
# We only want to see these events when the fit is first loaded (otherwise events will fire during the initial
# population of data). This sets listeners for all the relationships on fits. This allows us to update the fit's
# modified date whenever something is added/removed from fit
# See http://docs.sqlalchemy.org/en/rel_1_0/orm/events.html#sqlalchemy.orm.events.InstanceEvents.load
# todo: when we can, move over to `inspect(es_Fit).relationships` (when mac binaries are updated)
manager = getattr(target.__class__, "_sa_class_manager", None)
if manager:
for rel in manager.mapper.relationships:
if rel in ignored_rels:
continue
listen(rel, 'append', rel_listener)
listen(rel, 'remove', rel_listener)
listen(Fit, 'load', apply_rel_listeners)
listen(Module, 'load', apply_col_listeners)
listen(Drone, 'load', apply_col_listeners)
listen(Fighter, 'load', apply_col_listeners)
listen(Cargo, 'load', apply_col_listeners)
listen(Implant, 'load', apply_col_listeners)
listen(Booster, 'load', apply_col_listeners)

View File

@@ -21,6 +21,7 @@ import time
from copy import deepcopy
from itertools import chain
from math import sqrt, log, asinh
import datetime
from sqlalchemy.orm import validates, reconstructor
@@ -77,6 +78,8 @@ class Fit(object):
self.projected = False
self.name = name
self.timestamp = time.time()
self.created = None
self.modified = None
self.modeID = None
self.build()
@@ -180,6 +183,14 @@ class Fit(object):
self.__mode = mode
self.modeID = mode.item.ID if mode is not None else None
@property
def modifiedCoalesce(self):
"""
This is a property that should get whichever date is available for the fit. @todo: migrate old timestamp data
and ensure created / modified are set in database to get rid of this
"""
return self.modified or self.created or datetime.datetime.fromtimestamp(self.timestamp)
@property
def character(self):
return self.__character if self.__character is not None else Character.getAll0()