core: - individual parameters managed through sqlite
- new asyncGetParamA method, which allow to get parameter for a not connected profile ==> individual parameters are cached in memory when the profile is connected, but must be accessed though sqlite else, and that must be done asynchronously primitivus: - profile manager updated to use asyncGetParamA /!\ still broken, need more work before being able to run again
This commit is contained in:
parent
1982eb79d8
commit
554299aa91
7 changed files with 135 additions and 29 deletions
|
|
@ -62,6 +62,9 @@ class DBusBridgeFrontend(BridgeFrontend):
|
|||
def asyncConnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return self.db_core_iface.asyncConnect(profile_key, reply_handler=callback, error_handler=errback)
|
||||
|
||||
def asyncGetParamA(self, name, category, attribute="value", profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return unicode(self.db_core_iface.asyncGetParamA(name, category, attribute, profile_key, reply_handler=callback, error_handler=errback))
|
||||
|
||||
def callMenu(self, category, name, menu_type, profile_key):
|
||||
return unicode(self.db_core_iface.callMenu(category, name, menu_type, profile_key))
|
||||
|
||||
|
|
|
|||
|
|
@ -91,12 +91,15 @@ class ProfileManager(urwid.WidgetWrap):
|
|||
self.host.showPopUp(pop_up_widget)
|
||||
|
||||
def onProfileChange(self, list_wid):
|
||||
def setJID(jabberID):
|
||||
self.login_wid.set_edit_text(jabberID)
|
||||
def setPassword(password):
|
||||
self.pass_wid.set_edit_text(password)
|
||||
|
||||
profile_name = list_wid.getSelectedValue()
|
||||
if profile_name:
|
||||
jabberID = self.host.bridge.getParamA("JabberID", "Connection", profile_key=profile_name)
|
||||
password = self.host.bridge.getParamA("Password", "Connection", profile_key=profile_name)
|
||||
self.login_wid.set_edit_text(jabberID)
|
||||
self.pass_wid.set_edit_text(password)
|
||||
self.host.bridge.asyncGetParamA("JabberID", "Connection", profile_key=profile_name, callback=setJID, errback=self.getParamError)
|
||||
self.host.bridge.asyncGetParamA("Password", "Connection", profile_key=profile_name, callback=setPassword, errback=self.getParamError)
|
||||
|
||||
def onConnectProfile(self, button):
|
||||
profile_name = self.list_profile.getSelectedValue()
|
||||
|
|
@ -110,15 +113,24 @@ class ProfileManager(urwid.WidgetWrap):
|
|||
profile = self.host.bridge.getProfileName(profile_name)
|
||||
assert(profile)
|
||||
#TODO: move this to quick_app
|
||||
old_jid = self.host.bridge.getParamA("JabberID", "Connection", profile_key=profile)
|
||||
old_pass = self.host.bridge.getParamA("Password", "Connection", profile_key=profile)
|
||||
new_jid = self.login_wid.get_edit_text()
|
||||
new_pass = self.pass_wid.get_edit_text()
|
||||
self.host.bridge.asyncGetParamA("JabberID", "Connection", profile_key=profile,
|
||||
callback=lambda old_jid: self.__old_jidReceived(old_jid, profile), errback=self.getParamError)
|
||||
|
||||
if old_jid != new_jid:
|
||||
self.host.bridge.setParam("JabberID", new_jid, "Connection", profile)
|
||||
self.host.bridge.setParam("Server", JID(new_jid).domain, "Connection", profile)
|
||||
if old_pass != new_pass:
|
||||
self.host.bridge.setParam("Password", new_pass, "Connection", profile)
|
||||
self.host.plug_profile(profile)
|
||||
def __old_jidReceived(self, old_jid, profile):
|
||||
self.host.bridge.asyncGetParamA("Password", "Connection", profile_key=profile,
|
||||
callback=lambda old_pass: self.__old_passReceived(old_jid, old_pass, profile), errback=self.getParamError)
|
||||
|
||||
def __old_passReceived(self, old_jid, old_pass, profile):
|
||||
"""Check if we have new jid/pass, save them if it is the case, and plug profile"""
|
||||
new_jid = self.login_wid.get_edit_text()
|
||||
new_pass = self.pass_wid.get_edit_text()
|
||||
|
||||
if old_jid != new_jid:
|
||||
self.host.bridge.setParam("JabberID", new_jid, "Connection", profile)
|
||||
self.host.bridge.setParam("Server", JID(new_jid).domain, "Connection", profile)
|
||||
if old_pass != new_pass:
|
||||
self.host.bridge.setParam("Password", new_pass, "Connection", profile)
|
||||
self.host.plug_profile(profile)
|
||||
|
||||
def getParamError(self):
|
||||
error(_("Can't get profile parameter"))
|
||||
|
|
|
|||
|
|
@ -136,6 +136,12 @@ class DbusObject(dbus.service.Object):
|
|||
def asyncConnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return self.cb["asyncConnect"](unicode(profile_key), callback, errback)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='ssss', out_signature='s',
|
||||
async_callbacks=('callback', 'errback'))
|
||||
def asyncGetParamA(self, name, category, attribute="value", profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
return self.cb["asyncGetParamA"](unicode(name), unicode(category), unicode(attribute), unicode(profile_key), callback, errback)
|
||||
|
||||
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
|
||||
in_signature='ssss', out_signature='s',
|
||||
async_callbacks=None)
|
||||
|
|
|
|||
|
|
@ -360,6 +360,20 @@ sig_in=ssss
|
|||
sig_out=s
|
||||
param_2_default="value"
|
||||
param_3_default="@DEFAULT@"
|
||||
doc=Helper method to get a parameter's attribute *when profile is connected*
|
||||
doc_param_0=name: as for [setParam]
|
||||
doc_param_1=category: as for [setParam]
|
||||
doc_param_2=attribute: Name of the attribute
|
||||
doc_param_3=%(doc_profile_key)s
|
||||
|
||||
[asyncGetParamA]
|
||||
async=
|
||||
type=method
|
||||
category=core
|
||||
sig_in=ssss
|
||||
sig_out=s
|
||||
param_2_default="value"
|
||||
param_3_default="@DEFAULT@"
|
||||
doc=Helper method to get a parameter's attribute
|
||||
doc_param_0=name: as for [setParam]
|
||||
doc_param_1=category: as for [setParam]
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ class SAT(service.Service):
|
|||
self.bridge.register("getConfig", self.memory.getConfig)
|
||||
self.bridge.register("setParam", self.setParam)
|
||||
self.bridge.register("getParamA", self.memory.getParamA)
|
||||
self.bridge.register("asyncGetParamA", self.memory.asyncGetParamA)
|
||||
self.bridge.register("getParamsUI", self.memory.getParamsUI)
|
||||
self.bridge.register("getParams", self.memory.getParams)
|
||||
self.bridge.register("getParamsForCategory", self.memory.getParamsForCategory)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ SAVEFILE_HISTORY="/history"
|
|||
SAVEFILE_PRIVATE="/private" #file used to store misc values (mainly for plugins)
|
||||
SAVEFILE_DATABASE="/sat.db"
|
||||
|
||||
class ProfileNotInCacheError(Exception):
|
||||
pass
|
||||
|
||||
class Param():
|
||||
"""This class manage parameters with xml"""
|
||||
### TODO: add desciption in params
|
||||
|
|
@ -76,20 +79,18 @@ class Param():
|
|||
"""Load parameters template from file"""
|
||||
self.dom = minidom.parse(file)
|
||||
|
||||
def loadGenData(self, storage):
|
||||
def loadGenData(self):
|
||||
"""Load general parameters data from storage
|
||||
@param storage: xxxStorage object instance
|
||||
@return: deferred triggered once params are loaded"""
|
||||
return storage.loadGenParams(self.params_gen)
|
||||
return self.storage.loadGenParams(self.params_gen)
|
||||
|
||||
def loadIndData(self, storage, profile):
|
||||
def loadIndData(self, profile):
|
||||
"""Load individual parameters
|
||||
set self.params cache
|
||||
@param storage: xxxStorage object instance
|
||||
@param profile: profile to load (*must exist*)
|
||||
@return: deferred triggered once params are loaded"""
|
||||
self.params[profile] = {}
|
||||
return storage.loadIndParams(self.params, profile)
|
||||
return self.storage.loadIndParams(self.params, profile)
|
||||
|
||||
def save_xml(self, file):
|
||||
"""Save parameters template to xml file"""
|
||||
|
|
@ -109,9 +110,10 @@ class Param():
|
|||
with open(file+'_ind', 'w') as param_ind_pickle:
|
||||
pickle.dump(self.params, param_ind_pickle)
|
||||
|
||||
def __init__(self, host):
|
||||
def __init__(self, host, storage):
|
||||
debug("Parameters init")
|
||||
self.host = host
|
||||
self.storage = storage
|
||||
self.default_profile = None
|
||||
self.params = {}
|
||||
self.params_gen = {}
|
||||
|
|
@ -227,7 +229,7 @@ class Param():
|
|||
node = self.__getParamNode(name, category)
|
||||
if not node:
|
||||
error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category})
|
||||
return None
|
||||
return ""
|
||||
|
||||
if node[0] == 'general':
|
||||
value = self.__getParam(None, category, name, 'general')
|
||||
|
|
@ -239,12 +241,53 @@ class Param():
|
|||
if not profile:
|
||||
error(_('Requesting a param for an non-existant profile'))
|
||||
return ""
|
||||
|
||||
if profile not in self.params:
|
||||
error(_('Requesting synchronous param for not connected profile'))
|
||||
return ""
|
||||
|
||||
if attr == "value":
|
||||
return self.__getParam(profile, category, name) or node[1].getAttribute(attr)
|
||||
else:
|
||||
return node[1].getAttribute(attr)
|
||||
|
||||
def asyncGetParamA(self, name, category, attr="value", profile_key="@DEFAULT@", callback=None, errback=None):
|
||||
"""Helper method to get a specific attribute
|
||||
@param name: name of the parameter
|
||||
@param category: category of the parameter
|
||||
@param attr: name of the attribute (default: "value")
|
||||
@param profile: owner of the param (@ALL@ for everyone)
|
||||
@param callback: called when the profile is connected
|
||||
@param errback: called is the connection fail"""
|
||||
node = self.__getParamNode(name, category)
|
||||
if not node:
|
||||
error(_("Requested param [%(name)s] in category [%(category)s] doesn't exist !") % {'name':name, 'category':category})
|
||||
return None
|
||||
|
||||
if node[0] == 'general':
|
||||
value = self.__getParam(None, category, name, 'general')
|
||||
callback(value or node[1].getAttribute(attr))
|
||||
return
|
||||
|
||||
assert(node[0] == 'individual')
|
||||
|
||||
profile = self.getProfileName(profile_key)
|
||||
if not profile:
|
||||
error(_('Requesting a param for a non-existant profile'))
|
||||
errback()
|
||||
return
|
||||
|
||||
if attr != "value":
|
||||
callback(node[1].getAttribute(attr))
|
||||
return
|
||||
default = node[1].getAttribute(attr)
|
||||
try:
|
||||
callback(self.__getParam(profile, category, name) or default)
|
||||
except ProfileNotInCacheError:
|
||||
#We have to ask data to the storage manager
|
||||
d = self.storage.getIndParam(category, name, profile)
|
||||
d.addCallback(callback)
|
||||
d.addErrback(lambda x:errback())
|
||||
|
||||
def __getParam(self, profile, category, name, type='individual'):
|
||||
"""Return the param, or None if it doesn't exist
|
||||
|
|
@ -257,7 +300,9 @@ class Param():
|
|||
return self.params_gen[(category, name)]
|
||||
return None #This general param has the default value
|
||||
assert (type == 'individual')
|
||||
if not self.params.has_key(profile) or not self.params[profile].has_key((category, name)):
|
||||
if not self.params.has_key(profile):
|
||||
raise ProfileNotInCacheError
|
||||
if not self.params[profile].has_key((category, name)):
|
||||
return None
|
||||
return self.params[profile][(category, name)]
|
||||
|
||||
|
|
@ -418,7 +463,6 @@ class Memory:
|
|||
self.presenceStatus={}
|
||||
self.lastResource={} #tmp, will be refactored with bdd integration
|
||||
self.subscriptions={}
|
||||
self.params=Param(host)
|
||||
self.history={} #used to store chat history (key: short jid)
|
||||
self.private={} #used to store private value
|
||||
self.server_features={} #used to store discovery's informations
|
||||
|
|
@ -429,8 +473,9 @@ class Memory:
|
|||
host.set_const('savefile_database', SAVEFILE_DATABASE)
|
||||
database_file = os.path.expanduser(self.getConfig('','local_dir')+
|
||||
self.host.get_const('savefile_database'))
|
||||
self.loadFiles()
|
||||
self.storage = SqliteStorage(database_file)
|
||||
self.params=Param(host, self.storage)
|
||||
self.loadFiles()
|
||||
self.storage.initialized.addCallback(lambda ignore: self.load(init_defers))
|
||||
|
||||
defer.DeferredList(init_defers).chainDeferred(self.initialized)
|
||||
|
|
@ -506,7 +551,7 @@ class Memory:
|
|||
"""Load parameters and all memory things from db
|
||||
@param init_defers: list of deferred to wait before parameters are loaded"""
|
||||
#parameters data
|
||||
init_defers.append(self.params.loadGenData(self.storage))
|
||||
init_defers.append(self.params.loadGenData())
|
||||
|
||||
def loadIndividualParams(self, profile_key):
|
||||
"""Load individual parameters for a profile
|
||||
|
|
@ -764,6 +809,9 @@ class Memory:
|
|||
def getParamA(self, name, category, attr="value", profile_key='@DEFAULT@'):
|
||||
return self.params.getParamA(name, category, attr, profile_key)
|
||||
|
||||
def asyncGetParamA(self, name, category, attr="value", profile_key='@DEFAULT@', callback=None, errback=None):
|
||||
return self.params.asyncGetParamA(name, category, attr, profile_key, callback, errback)
|
||||
|
||||
def getParamsUI(self, profile_key):
|
||||
return self.params.getParamsUI(profile_key)
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ class SqliteStorage():
|
|||
@param params_gen: dictionary to fill
|
||||
@return: deferred"""
|
||||
def fillParams(result):
|
||||
params_gen[(category, name)] = value
|
||||
for param in result:
|
||||
category,name,value = param
|
||||
params_gen[(category, name)] = value
|
||||
debug(_("loading general parameters from database"))
|
||||
return self.dbpool.runQuery("SELECT category,name,value FROM param_gen").addCallback(fillParams)
|
||||
|
||||
|
|
@ -108,12 +110,25 @@ class SqliteStorage():
|
|||
@param profile: a profile which *must* exist
|
||||
@return: deferred"""
|
||||
def fillParams(result):
|
||||
params_ind[profile][(category, name)] = value
|
||||
for param in result:
|
||||
category,name,value = param
|
||||
params_ind[profile][(category, name)] = value
|
||||
debug(_("loading individual parameters from database"))
|
||||
d = self.dbpool.runQuery("SELECT category,name,value FROM param_gen WHERE profile_id=?", self.profiles[profile])
|
||||
d.addCallback(fillParams)
|
||||
return d
|
||||
|
||||
def getIndParam(self, category, name, profile):
|
||||
"""Ask database for the value of one specific individual parameter
|
||||
@param category: category of the parameter
|
||||
@param name: name of the parameter
|
||||
@param profile: %(doc_profile)s
|
||||
@return: deferred"""
|
||||
d = self.dbpool.runQuery("SELECT value FROM param_ind WHERE category=? AND name=? AND profile_id=?", (category,name,self.profiles[profile]))
|
||||
d.addCallback(self.__getFirstResult)
|
||||
return d
|
||||
|
||||
|
||||
def setGenParam(self, category, name, value):
|
||||
"""Save the general parameters in database
|
||||
@param category: category of the parameter
|
||||
|
|
@ -134,3 +149,10 @@ class SqliteStorage():
|
|||
d = self.dbpool.runQuery("REPLACE INTO param_ind(category,name,profile_id,value) VALUES (?,?,?,?)", (category, name, self.profiles[profile], value))
|
||||
d.addErrback(lambda ignore: error(_("Can't set individual parameter (%(category)s/%(name)s) for [%(profile)s] in database" % {"category":category, "name":name, "profile":profile})))
|
||||
return d
|
||||
|
||||
##Helper methods##
|
||||
|
||||
def __getFirstResult(self, result):
|
||||
"""Return the first result of a database query
|
||||
Useful when we are looking for one specific value"""
|
||||
return "" if not result else result[0][0]
|
||||
|
|
|
|||
Loading…
Reference in a new issue