# HG changeset patch # User Goffi # Date 1295887665 -3600 # Node ID c4b84a2d2ad1d747d02cf345a106d0a98d59db3d # Parent b5f1f3dc9ac6bfa0aaae43f5d45c3485c1ffa395 bridge: constructor and template improved, documentation added diff -r b5f1f3dc9ac6 -r c4b84a2d2ad1 frontends/src/quick_frontend/quick_app.py --- a/frontends/src/quick_frontend/quick_app.py Mon Jan 24 01:22:00 2011 +0100 +++ b/frontends/src/quick_frontend/quick_app.py Mon Jan 24 17:47:45 2011 +0100 @@ -188,7 +188,7 @@ self.contactList.clear_contacts() self.setStatusOnline(False) - def connection_error(self, profile, error_type): + def connection_error(self, error_type, profile): """called when something goest wrong with the connection""" if not self.check_profile(profile): return diff -r b5f1f3dc9ac6 -r c4b84a2d2ad1 src/bridge/DBus.py --- a/src/bridge/DBus.py Mon Jan 24 01:22:00 2011 +0100 +++ b/src/bridge/DBus.py Mon Jan 24 17:47:45 2011 +0100 @@ -24,7 +24,6 @@ import dbus import dbus.service import dbus.mainloop.glib -import pdb from logging import debug, info, error const_INT_PREFIX = "org.goffi.SAT" #Interface prefix @@ -55,7 +54,7 @@ @dbus.service.signal(const_INT_PREFIX+const_COMM_SUFFIX, signature='ss') - def connection_error(self, profile, error_type): + def connection_error(self, error_type, profile): debug("Connection_error signal") @dbus.service.signal(const_INT_PREFIX+const_COMM_SUFFIX, @@ -142,7 +141,7 @@ in_signature='s', out_signature='i') def deleteProfile(self, name): info ('Profile deletion asked') - return self.cb["deleteProfile"](str(name)) + return self.cb["deleteProfile"](unicode(name)) @dbus.service.method(const_INT_PREFIX+const_COMM_SUFFIX, in_signature='sssi', out_signature='s') @@ -163,7 +162,7 @@ return self.cb["disconnect"](profile_key) @dbus.service.method(const_INT_PREFIX+const_COMM_SUFFIX, - in_signature='', out_signature='b') + in_signature='s', out_signature='b') def isConnected(self, profile_key='@DEFAULT@'): info ("Connection status asked") return self.cb["isConnected"](profile_key) diff -r b5f1f3dc9ac6 -r c4b84a2d2ad1 src/bridge/bridge_contructor.py --- a/src/bridge/bridge_contructor.py Mon Jan 24 01:22:00 2011 +0100 +++ b/src/bridge/bridge_contructor.py Mon Jan 24 17:47:45 2011 +0100 @@ -41,8 +41,9 @@ import os from os import path from optparse import OptionParser -from ConfigParser import RawConfigParser as Parser +from ConfigParser import SafeConfigParser as Parser from ConfigParser import NoOptionError +import re class ParseError(Exception): @@ -67,8 +68,49 @@ value = None function[option] = value return function + + def getDefault(self, name): + """Return default values of a function in a dict + @param name: Name of the function to get + @return: dict, each key is the integer param number (no key if no default value)""" + default_dict={} + def_re = re.compile(r"param_(\d+)_default") + + for option in self.bridge_template.options(name): + if option == 'doc_return': + default_dict['return'] = self.bridge_template.get(name, option) + continue + match = def_re.match(option) + if match: + try: + idx = int(match.group(1)) + except ValueError: + raise ParseError("Invalid value [%s] for parameter number" % match.group(1)) + default_dict[idx] = self.bridge_template.get(name, option) + + return default_dict - def getArguments(self, signature): + def getArgumentsDoc(self, name): + """Return documentation of arguments + @param name: Name of the function to get + @return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)""" + doc_dict={} + option_re = re.compile(r"doc_param_(\d+)") + value_re = re.compile(r"^(\w+): (.*)$", re.MULTILINE | re.DOTALL) + for option in self.bridge_template.options(name): + match = option_re.match(option) + if match: + try: + idx = int(match.group(1)) + except ValueError: + raise ParseError("Invalid value [%s] for parameter number" % match.group(1)) + value_match = value_re.match(self.bridge_template.get(name, option)) + if not value_match: + raise ParseError("Invalid value for parameter doc [%i]" % idx) + doc_dict[idx]=(value_match.group(1),value_match.group(2)) + return doc_dict + + def getArguments(self, signature, name=None, default=None): """Return arguments to user given a signature @param signature: signature in the short form (using s,a,i,b etc) @return: list of arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")""" @@ -79,7 +121,10 @@ if signature[i] not in ['b','y','n','i','x','q','u','t','d','s','a']: raise ParseError("Unmanaged attribute type [%c]" % signature[i]) - attr_string += ("" if idx==0 else ", ") + ("arg_%i" % idx) + attr_string += ("" if idx==0 else ", ") + ("%(name)s%(default)s" % { + 'name':name[idx][0] if (name and name.has_key(idx)) else "arg_%i" % idx, + 'default':"="+default[idx] if (default and default.has_key(idx)) else '' + }) #give arg_1, arg2, etc or name1, name2=default, etc idx+=1 if signature[i] == 'a': @@ -88,6 +133,7 @@ i+=1 continue #we have a simple type for the array opening_car = signature[i] + assert(opening_car in ['{','(']) closing_car = '}' if opening_car == '{' else ')' opening_count = 1 while (True): #we have a dict or a list of tuples @@ -123,12 +169,14 @@ for section in sections: function = self.getValues(section) print ("Adding %s %s" % (section, function["type"])) + default = self.getDefault(section) + arg_doc = self.getArgumentsDoc(section) completion = { 'sig_in':function['sig_in'] or '', 'sig_out':function['sig_out'] or '', 'category':'REQ' if function['category'] == 'request' else 'COMM', 'name':section, - 'args':self.getArguments(function['sig_in']) + 'args':self.getArguments(function['sig_in'], name=arg_doc, default=default, ) } if function["type"] == "signal": @@ -146,11 +194,12 @@ elif function["type"] == "method": completion['debug'] = "" if not self.options.debug else 'debug ("%s")\n%s' % (section,8*' ') + completion['args_nodefault'] = self.getArguments(function['sig_in'], name=arg_doc) methods_part.append("""\ @dbus.service.method(const_INT_PREFIX+const_%(category)s_SUFFIX, in_signature='%(sig_in)s', out_signature='%(sig_out)s') def %(name)s(self, %(args)s): - %(debug)sreturn self.cb["%(name)s"](%(args)s) + %(debug)sreturn self.cb["%(name)s"](%(args_nodefault)s) """ % completion) #at this point, signals_part, methods_part and direct_calls should be filled, diff -r b5f1f3dc9ac6 -r c4b84a2d2ad1 src/bridge/bridge_template.ini --- a/src/bridge/bridge_template.ini Mon Jan 24 01:22:00 2011 +0100 +++ b/src/bridge/bridge_template.ini Mon Jan 24 17:47:45 2011 +0100 @@ -1,3 +1,7 @@ +[DEFAULT] +doc_profile=profile: Name of the profile. +doc_profile_key=profile_key: Profile key which can be either a magic (eg: @DEFAULT@) or the name of an existing profile. + ;signals [connected] @@ -5,84 +9,140 @@ category=communication sig_in=s doc=Connection is done +doc_param_0=%(doc_profile)s [disconnected] type=signal category=communication sig_in=s doc=Connection is finished or lost +doc_param_0=%(doc_profile)s [connection_error] type=signal category=communication sig_in=ss doc=Something went wront with the connection +doc_param_0=error_type: Why the connection got wrong, can be + - AUTH_ERROR: Authentification error +doc_param_1=%(doc_profile)s [newContact] type=signal category=communication sig_in=sa{ss}ass doc=New contact received in roster +doc_param_0=contact: JID from who the message is comming +doc_param_1=attributes: Dictionary of attributes where keys are: + - name: name of the contact + - to: "True" if the contact give its presence information to us + - from: "True" if contact is registred to our presence information + - ask: "True" is subscription is pending +doc_param_2=groups: Roster's groups where the contact is +doc_param_3=%(doc_profile)s [newMessage] type=signal category=communication sig_in=sssss doc=A message has been received +doc_param_0=from_jid: JID where the message is comming from +doc_param_1=message: Message itself +doc_param_2=mess_type: Type of the message (cf RFC 3921 #2.1.1) +doc_param_3=to_jid: JID where the message must be sent +doc_param_4=%(doc_profile)s [newAlert] type=signal category=communication sig_in=ssss -doc=A message has been received +doc=A new alert happened +doc_param_0=message: Body of the alert +doc_param_1=title: Title of the alert +doc_param_2=alert_type: Type of the alert, can be: + - INFO: Informative message + - ERROR: something went wrong +doc_param_3=%(doc_profile)s [presenceUpdate] type=signal category=communication sig_in=ssia{ss}s doc=Somebody changed his presence informations. +doc_param_0=entity: JID from which we have presence informations +doc_param_1=show: availability status (see RFC 3921 #2.2.2.1) +doc_param_2=priority: Priority level of the ressource (see RFC 3921 #2.2.2.3) +doc_param_3=statuses: Natural language description of the availability status (see RFC 3921 #2.2.2.2) +doc_param_4=%(doc_profile)s [subscribe] type=signal category=communication sig_in=sss -doc=Somebody wants to be added in roster list +doc=Somebody wants to be added in roster +doc_param_0=sub_type: Subscription states (see RFC 3921 #9) +doc_param_1=entity: JID from which the subscription is coming +doc_param_2=%(doc_profile)s [paramUpdate] type=signal category=communication sig_in=ssss doc=A parameter has been changed +doc_param_0=name: Name of the updated parameter +doc_param_1=value: New value of the parameter +doc_param_2=category: Category of the updated parameter +doc_param_3=%(doc_profile)s [contactDeleted] type=signal category=communication sig_in=ss -doc=A contact has been supressed from roster list +doc=A contact has been supressed from roster +doc_param_0=entity: JID of the contact removed from roster +doc_param_1=%(doc_profile)s [askConfirmation] type=signal category=request sig_in=ssa{ss} doc=A confirmation is needed for an action +doc_param_0=conf_type: Type of the confirmation, can be: + - YES/NO: A question which need a yes or no answer + - FILE_TRANSFERT: A confirmation is needed before transfering a file +doc_param_1=id: Id of the confirmation query +doc_param_2=data: conf_type dependent data [actionResult] type=signal category=request sig_in=ssa{ss} doc=Requested result of an action +doc_param_0=answer_type: Type of the answer, can be: + - SUPPRESS: The action is managed, the id MUST be removed from queue + - XMLUI: A SàT XMLUI interface is sent + - ERROR: Something went wrong when doing the action + - RESULT: General result, interpretation depend of the action +doc_param_1=id: Id of the action +doc_param_2=data: answer_type specific data [actionResultExt] type=signal category=request sig_in=ssa{sa{ss}} doc=Requested result of an action (Extended) +doc_param_0=answer_type: Same as for [actionResult] but with the following additional one: + - DICT_DICT: As RESULT, but returned as a dictionary of dictionary +doc_param_1=id: Id of the action +doc_param_2=data: answer_type specific data [updatedValue] type=signal category=request sig_in=sa{ss} doc=A value has been updated +doc_param_0=name: Name of the updated value +doc_param_1=value: New value ;methods @@ -99,6 +159,7 @@ sig_in=s sig_out=s doc=Get real profile name from profile key +doc_param_0=%(doc_profile_key)s [getProfilesList] type=method @@ -113,6 +174,10 @@ sig_in=s sig_out=i doc=Create a new profile +doc_param_0=%(doc_profile)s +doc_return=status of the creation: + - 0: Profile created + - 1: The profile name already exists [deleteProfile] type=method @@ -120,13 +185,23 @@ sig_in=s sig_out=i doc=Delete a profile +doc_param_0=%(doc_profile)s +doc_return=status of the deletion: + - 0: Profile deleted + - 1: The profile doesn't exists [registerNewAccount] +deprecated= type=method category=communication sig_in=sssi sig_out=s +param_3_default=5222 doc=Register a new account on a given server +doc_param_0=login: login of the account +doc_param_1=password: password of the account +doc_param_2=host: host of the server to register to +doc_param_3=port: port of the server to register to [connect] type=method @@ -135,6 +210,7 @@ sig_out= param_0_default="@DEFAULT@" doc=Connect a profile +doc_param_0=%(doc_profile_key)s [disconnect] type=method @@ -143,14 +219,16 @@ sig_out= param_0_default="@DEFAULT@" doc=Disconnect a profile +doc_param_0=%(doc_profile_key)s [isConnected] type=method category=communication -sig_in= +sig_in=s sig_out=b param_0_default="@DEFAULT@" doc=Tell if a profile is connected +doc_param_0=%(doc_profile_key)s [getContacts] type=method @@ -159,6 +237,11 @@ sig_out=a(sa{ss}as) param_0_default="@DEFAULT@" doc=Return informations about all contacts +doc_param_0=%(doc_profile_key)s +doc_return=array of tuples with the following values: + - JID of the contact + - list of attributes as in [newContact] + - groups where the contact is [getPresenceStatus] type=method @@ -167,6 +250,9 @@ sig_out=a{sa{s(sia{ss})}} param_0_default="@DEFAULT@" doc=Return presence informations of all contacts +doc_param_0=%(doc_profile_key)s +doc_return=Dict of presence with bare JID of contact as key, and value as follow: + A dict where key is the resource and the value is a tuple with (show, priority, statuses) as for [presenceUpdate] [getWaitingSub] type=method @@ -175,22 +261,40 @@ sig_out=a{ss} param_0_default="@DEFAULT@" doc=Get subscription requests in queue +doc_param_0=%(doc_profile_key)s +doc_return=Dict where contact JID is the key, and value is the subscription type [sendMessage] type=method category=communication sig_in=sssss sig_out= +param_2_default="" +param_3_default="chat" param_4_default="@DEFAULT@" doc=Send a message +doc_param_0=to_jid: JID of the recipient +doc_param_1=message: body of the message +doc_param_2=subject: Subject of the message ("" if no subject) +doc_param_3=mess_type: Type of the message (cf RFC 3921 #2.1.1) +doc_param_4=%(doc_profile_key)s [setPresence] type=method category=communication sig_in=ssia{ss}s sig_out= +param_0_default="" +param_1_default="" +param_2_default=0 +param_3_default={} param_4_default="@DEFAULT@" doc=Set presence information for the profile +doc_param_0=to_jid: the JID to who we send the presence data (emtpy string for broadcast) +doc_param_1=show: as for [presenceUpdate] +doc_param_2=priority: as for [presenceUpdate] +doc_param_3=statuses: as for [presenceUpdate] +doc_param_4=%(doc_profile_key)s [subscription] type=method @@ -199,6 +303,9 @@ sig_out= param_2_default="@DEFAULT@" doc=Send subscription request/answer to a contact +doc_param_0=sub_type: as for [subscribe] +doc_param_1=entity: as for [subscribe] +doc_param_2=%(doc_profile_key)s [setParam] type=method @@ -207,6 +314,10 @@ sig_out= param_3_default="@DEFAULT@" doc=Change a parameter +doc_param_0=name: Name of the parameter to change +doc_param_1=value: New Value of the parameter +doc_param_2=category: Category of the parameter to change +doc_param_3=%(doc_profile_key)s [getParamA] type=method @@ -215,6 +326,9 @@ sig_out=s param_2_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] +doc_param_2=%(doc_profile_key)s [getParamsUI] type=method @@ -223,6 +337,7 @@ sig_out=s param_0_default="@DEFAULT@" doc=Return a SàT XMLUI for parameters +doc_param_0=%(doc_profile_key)s [getParams] type=method @@ -231,6 +346,7 @@ sig_out=s param_0_default="@DEFAULT@" doc=Return XML of parameters +doc_param_0=%(doc_profile_key)s [getParamsForCategory] type=method @@ -238,7 +354,9 @@ sig_in=ss sig_out=s param_1_default="@DEFAULT@" -doc=Return a xml of all params in a category +doc=Return a xml of all params in a category +doc_param_0=category: Category to get +doc_param_1=%(doc_profile_key)s [getParamsCategories] type=method @@ -246,6 +364,7 @@ sig_in= sig_out=as doc=Get all categories currently existing in parameters +doc_return=list of categories [getHistory] type=method @@ -253,6 +372,10 @@ sig_in=ssi sig_out=a{i(ss)} doc=Get history of a communication between two entities +doc_param_0=from_jid: source JID +doc_param_1=to_jid: dest JID +doc_param_2=size: size of the history (0 for the whole history) +doc_return=Dict where key is timestamp (seconds this the Epoch), and value is a tuple (from_jid, to_jid) [addContact] type=method @@ -260,7 +383,9 @@ sig_in=ss sig_out= param_1_default="@DEFAULT@" -doc=Add a contact to profile's roster list +doc=Add a contact to profile's roster +doc_param_0=entity: JID to add to roster +doc_param_1=%(doc_profile_key)s [delContact] type=method @@ -268,7 +393,9 @@ sig_in=ss sig_out= param_1_default="@DEFAULT@" -doc=Remove a contact from profile's roster list +doc=Remove a contact from profile's roster +doc_param_0=entity: JID to remove from roster +doc_param_1=%(doc_profile_key)s [launchAction] type=method @@ -277,6 +404,10 @@ sig_out=s param_2_default="@DEFAULT@" doc=Launch a specific action +doc_param_0=action_type: type of the action which can be: + - button: A button is pushed +doc_param_1=data: action_type dependant data +doc_param_2=%(doc_profile_key)s [confirmationAnswer] type=method @@ -284,6 +415,9 @@ sig_in=sba{ss} sig_out= doc=Give answer to a confirmation request +doc_param_0=id: id of the confirmation request +doc_param_1=accepted: True if the action is confirmed +doc_param_2=data: action specific data [getProgress] type=method @@ -291,6 +425,10 @@ sig_in=s sig_out=a{ss} doc=Get progress information for an action +doc_param_0=id: id of the progression status +doc_return=dict with progress information: + - position: current position + - size: end position [getMenus] type=method @@ -298,6 +436,11 @@ sig_in= sig_out=a(sss) doc=Get all additional menus +doc_return=list of tuple with the following value: + - category: Category of the menu + - name: Name of the menu + - menu_type: Type which can be: + * NORMAL: Classical application menu [getMenuHelp] type=method @@ -305,7 +448,11 @@ sig_in=sss sig_out=s param_2="NORMAL" -doc=Get help informationd for a menu +doc=Get help information for a menu +doc_param_0=category: Category of the menu +doc_param_1=name: Name of the menu +doc_param_2=menu_type: Type of the menu as in [getMenus] return value +doc_return=Help string [callMenu] type=method @@ -313,4 +460,8 @@ sig_in=ssss sig_out=s doc=Execute action associated with a menu - +doc_param_0=category: as in [getMenuHelp] +doc_param_1=name: as in [getMenuHelp] +doc_param_2=menu_type: as in [getMenuHelp] +doc_param_3=%(doc_profile_key)s +doc_return=return an actionId or the empty string if something went wrong diff -r b5f1f3dc9ac6 -r c4b84a2d2ad1 src/sat.tac --- a/src/sat.tac Mon Jan 24 01:22:00 2011 +0100 +++ b/src/sat.tac Mon Jan 24 17:47:45 2011 +0100 @@ -108,7 +108,7 @@ def initializationFailed(self, reason): print ("initializationFailed: %s" % reason) - self.host_app.bridge.connection_error(self.profile,"AUTH_ERROR") + self.host_app.bridge.connection_error("AUTH_ERROR", self.profile) try: client.XMPPClient.initializationFailed(self, reason) except: @@ -793,7 +793,7 @@ return "" def callMenu(self, category, name, type="NORMAL", profile_key='@DEFAULT@'): - """return the help string of the menu""" + """return the id of the action""" profile = self.memory.getProfileName(profile_key) if not profile_key: error (_('Non-exsitant profile'))