From f9b7376cc78fce401ad885026a753f68c6e0ddd3 Mon Sep 17 00:00:00 2001 From: blitzmann Date: Wed, 26 Apr 2017 19:34:47 -0400 Subject: [PATCH] Move sql alchemy events into their own file for now so that mac-deprecated doesn't get pissy. --- eos/db/saveddata/fit.py | 25 ----------------- eos/db/saveddata/module.py | 28 ------------------- eos/events.py | 55 ++++++++++++++++++++++++++++++++++++++ gui/shipBrowser.py | 1 - pyfa.py | 7 +++++ 5 files changed, 62 insertions(+), 54 deletions(-) create mode 100644 eos/events.py diff --git a/eos/db/saveddata/fit.py b/eos/db/saveddata/fit.py index 5f3c12879..9853f7247 100644 --- a/eos/db/saveddata/fit.py +++ b/eos/db/saveddata/fit.py @@ -17,11 +17,9 @@ # along with eos. If not, see . # =============================================================================== -import datetime from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm.collections import attribute_mapped_collection from sqlalchemy.sql import and_ -from sqlalchemy.event import listen from sqlalchemy.orm import relation, reconstructor, mapper, relationship from sqlalchemy import ForeignKey, Column, Integer, String, Table, Boolean, DateTime import sqlalchemy.sql.functions as func @@ -248,26 +246,3 @@ mapper(ProjectedFit, projectedFits_table, mapper(CommandFit, commandFits_table) -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 load_listener(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(es_Fit, "_sa_class_manager", None) - if manager: - for rel in manager.mapper.relationships: - listen(rel, 'append', rel_listener) - listen(rel, 'remove', rel_listener) - -listen(Module, 'load', load_listener) - diff --git a/eos/db/saveddata/module.py b/eos/db/saveddata/module.py index 6993e53fa..fbbf9332a 100644 --- a/eos/db/saveddata/module.py +++ b/eos/db/saveddata/module.py @@ -19,11 +19,8 @@ from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Boolean, DateTime, select from sqlalchemy.orm import relation, mapper -from sqlalchemy.event import listen import sqlalchemy.sql.functions as func -import datetime - from eos.db import saveddata_meta from eos.saveddata.module import Module from eos.saveddata.fit import Fit @@ -45,29 +42,4 @@ mapper(Module, modules_table, properties={"owner": relation(Fit)}) -def update_fit_modified(target, value, oldvalue, initiator): - if not target.owner: - return - - if value != oldvalue: - print "{} had a module change".format(target.owner) - target.owner.modified = datetime.datetime.now() - - -def load_listener(target, context): - # We only want to se 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(Module, "_sa_class_manager", None) - if manager: - for col in manager.mapper.column_attrs: - listen(col, 'set', update_fit_modified) - - -listen(Module, 'load', load_listener) - diff --git a/eos/events.py b/eos/events.py new file mode 100644 index 000000000..6284aee98 --- /dev/null +++ b/eos/events.py @@ -0,0 +1,55 @@ +# 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 eos.saveddata.fit import Fit +from eos.saveddata.module import Module + + +def update_fit_modified(target, value, oldvalue, initiator): + if not target.owner: + return + + if value != oldvalue: + print "{} had a change via {}".format(target.owner, target) + target.owner.modified = datetime.datetime.now() + + +def apply_col_listeners(target, context): + # We only want to se 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: + listen(rel, 'append', rel_listener) + listen(rel, 'remove', rel_listener) + +listen(Fit, 'load', apply_rel_listeners) +listen(Module, 'load', apply_col_listeners) \ No newline at end of file diff --git a/gui/shipBrowser.py b/gui/shipBrowser.py index 78f12b26b..958c5e07f 100644 --- a/gui/shipBrowser.py +++ b/gui/shipBrowser.py @@ -7,7 +7,6 @@ import time import wx # noinspection PyPackageRequirements from wx.lib.buttons import GenBitmapButton -import datetime from service.fit import Fit from service.market import Market diff --git a/pyfa.py b/pyfa.py index 9367f67ab..2fec5fb2a 100755 --- a/pyfa.py +++ b/pyfa.py @@ -341,6 +341,7 @@ if __name__ == "__main__": else: saVersion = sqlalchemy.__version__ saMatch = re.match("([0-9]+).([0-9]+)([b\.])([0-9]+)", saVersion) + config.saVersion = (int(saMatch.group(1)), int(saMatch.group(2)), int(saMatch.group(4))) if saMatch: saMajor = int(saMatch.group(1)) saMinor = int(saMatch.group(2)) @@ -370,6 +371,12 @@ if __name__ == "__main__": pyfalog.warning("Recommended version {0} {1}", requirement_parsed[1], requirement_parsed[2]) import eos.db + + if config.saVersion[0] > 0 or config.saVersion[1] >= 7: + # <0.7 doesn't have support for events ;_; (mac-deprecated) + config.sa_events = True + import eos.events + # noinspection PyUnresolvedReferences import service.prefetch # noqa: F401