comparison src/bridge/bridge_constructor/bridge_contructor.py @ 374:193fd5995430

bridge-constructor: added dbus-xml constructor (used for Qt frontend)
author Goffi <goffi@goffi.org>
date Thu, 28 Jul 2011 03:02:31 +0200
parents 3ea41a199b36
children 502489e17685
comparison
equal deleted inserted replaced
373:a3aa4d046914 374:193fd5995430
33 under certain conditions. 33 under certain conditions.
34 --- 34 ---
35 35
36 This script construct a SàT bridge using the given protocol 36 This script construct a SàT bridge using the given protocol
37 """ 37 """
38 MANAGED_PROTOCOLES=['dbus','mediawiki'] 38 MANAGED_PROTOCOLES=['dbus','mediawiki', 'dbus-xml']
39 DEFAULT_PROTOCOLE='dbus' 39 DEFAULT_PROTOCOLE='dbus'
40 FLAGS=['deprecated', 'async'] 40 FLAGS=['deprecated', 'async']
41 41
42 ENV_OVERRIDE = "SAT_BRIDGE_CONST_" #Prefix used to override a constant 42 ENV_OVERRIDE = "SAT_BRIDGE_CONST_" #Prefix used to override a constant
43 43
47 from optparse import OptionParser 47 from optparse import OptionParser
48 from ConfigParser import SafeConfigParser as Parser 48 from ConfigParser import SafeConfigParser as Parser
49 from ConfigParser import NoOptionError 49 from ConfigParser import NoOptionError
50 import re 50 import re
51 from datetime import datetime 51 from datetime import datetime
52 from xml.dom import minidom
52 53
53 54
54 class ParseError(Exception): 55 class ParseError(Exception):
55 #Used when the signature parsing is going wrong (invalid signature ?) 56 #Used when the signature parsing is going wrong (invalid signature ?)
56 pass 57 pass
130 @param name: Name of the function to get 131 @param name: Name of the function to get
131 @return: string documentation, or None""" 132 @return: string documentation, or None"""
132 if self.bridge_template.has_option(name, "doc"): 133 if self.bridge_template.has_option(name, "doc"):
133 return self.bridge_template.get(name, "doc") 134 return self.bridge_template.get(name, "doc")
134 return None 135 return None
135 136
136 def getArguments(self, signature, name=None, default=None, unicode_protect=False): 137
137 """Return arguments to user given a signature 138 def argumentsParser(self, signature):
138 @param signature: signature in the short form (using s,a,i,b etc) 139 """Generator which return individual arguments signatures from a global signature"""
139 @param name: dictionary of arguments name like given by getArguments 140 start=0
140 @param default: dictionary of default values, like given by getDefault
141 @param unicode_protect: activate unicode protection on strings (return strings as unicode(str))
142 @return: list of arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")"""
143 i=0 141 i=0
144 idx=0 142
145 attr_string=[]
146 while i<len(signature): 143 while i<len(signature):
147 if signature[i] not in ['b','y','n','i','x','q','u','t','d','s','a']: 144 if signature[i] not in ['b','y','n','i','x','q','u','t','d','s','a']:
148 raise ParseError("Unmanaged attribute type [%c]" % signature[i]) 145 raise ParseError("Unmanaged attribute type [%c]" % signature[i])
149
150 attr_string.append(("unicode(%(name)s)%(default)s" if (unicode_protect and signature[i]=='s') else "%(name)s%(default)s") % {
151 'name':name[idx][0] if (name and name.has_key(idx)) else "arg_%i" % idx,
152 'default':"="+default[idx] if (default and default.has_key(idx)) else ''
153 }) #give arg_1, arg2, etc or name1, name2=default, etc. \
154 #give unicode(arg_1), unicode(arg_2), etc. if unicode_protect is set and arg is a string
155 idx+=1
156 146
157 if signature[i] == 'a': 147 if signature[i] == 'a':
158 i+=1 148 i+=1
159 if signature[i]!='{' and signature[i]!='(': #FIXME: must manage tuples out of arrays 149 if signature[i]!='{' and signature[i]!='(': #FIXME: must manage tuples out of arrays
160 i+=1 150 i+=1
151 yield signature[start:i]
152 start=i
161 continue #we have a simple type for the array 153 continue #we have a simple type for the array
162 opening_car = signature[i] 154 opening_car = signature[i]
163 assert(opening_car in ['{','(']) 155 assert(opening_car in ['{','('])
164 closing_car = '}' if opening_car == '{' else ')' 156 closing_car = '}' if opening_car == '{' else ')'
165 opening_count = 1 157 opening_count = 1
172 if signature[i] == closing_car: 164 if signature[i] == closing_car:
173 opening_count-=1 165 opening_count-=1
174 if opening_count == 0: 166 if opening_count == 0:
175 break 167 break
176 i+=1 168 i+=1
169 yield signature[start:i]
170 start=i
171
172 def getArguments(self, signature, name=None, default=None, unicode_protect=False):
173 """Return arguments to user given a signature
174 @param signature: signature in the short form (using s,a,i,b etc)
175 @param name: dictionary of arguments name like given by getArguments
176 @param default: dictionary of default values, like given by getDefault
177 @param unicode_protect: activate unicode protection on strings (return strings as unicode(str))
178 @return: list of arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")"""
179 idx=0
180 attr_string=[]
181
182 for arg in self.argumentsParser(signature):
183 attr_string.append(("unicode(%(name)s)%(default)s" if (unicode_protect and arg=='s') else "%(name)s%(default)s") % {
184 'name':name[idx][0] if (name and name.has_key(idx)) else "arg_%i" % idx,
185 'default':"="+default[idx] if (default and default.has_key(idx)) else ''
186 }) #give arg_1, arg2, etc or name1, name2=default, etc. \
187 #give unicode(arg_1), unicode(arg_2), etc. if unicode_protect is set and arg is a string
188 idx+=1
189
177 return ", ".join(attr_string) 190 return ", ".join(attr_string)
178 191
179 def generateCoreSide(self): 192 def generateCoreSide(self):
180 """create the constructor in SàT core side (backend)""" 193 """create the constructor in SàT core side (backend)"""
181 raise NotImplementedError 194 raise NotImplementedError
460 sys.exit(1) 473 sys.exit(1)
461 474
462 #now we write to final file 475 #now we write to final file
463 self.finalWrite(self.frontend_dest, frontend_bridge) 476 self.finalWrite(self.frontend_dest, frontend_bridge)
464 477
478 class DbusXmlConstructor(Constructor):
479 """Constructor for DBus XML syntaxt (used by Qt frontend)"""
480
481 def __init__(self, bridge_template, options):
482 Constructor.__init__(self, bridge_template, options)
483
484 self.template="dbus_xml_template.xml"
485 self.core_dest="org.goffi.sat.xml"
486
487 def generateCoreSide(self):
488 try:
489 doc = minidom.parse(self.template)
490 interface_elt = doc.getElementsByTagName('interface')[0]
491 except IOError:
492 print ("Can't access template")
493 sys.exit(1)
494 except IndexError:
495 print ("Template error")
496 sys.exit(1)
497
498 sections = self.bridge_template.sections()
499 sections.sort()
500 for section in sections:
501 function = self.getValues(section)
502 print ("Adding %s %s" % (section, function["type"]))
503 new_elt = doc.createElement('method' if function["type"]=='method' else 'signal')
504 new_elt.setAttribute('name', section)
505 args_in_str = self.getArguments(function['sig_in'])
506
507 idx=0
508 args_doc = self.getArgumentsDoc(section)
509 for arg in self.argumentsParser(function['sig_in'] or ''):
510 arg_elt = doc.createElement('arg')
511 arg_elt.setAttribute('name', args_doc[idx][0] if args_doc.has_key(idx) else "arg_%i" % idx)
512 arg_elt.setAttribute('type', arg)
513 arg_elt.setAttribute('direction', 'in' if function["type"]=='method' else 'out')
514 new_elt.appendChild(arg_elt)
515 idx+=1
516
517 if function['sig_out']:
518 arg_elt = doc.createElement('arg')
519 arg_elt.setAttribute('type', function['sig_out'])
520 arg_elt.setAttribute('direction', 'out')
521 new_elt.appendChild(arg_elt)
522
523 interface_elt.appendChild(new_elt)
524
525 #now we write to final file
526 self.finalWrite(self.core_dest, [doc.toprettyxml()])
465 527
466 class ConstructorError(Exception): 528 class ConstructorError(Exception):
467 pass 529 pass
468 530
469 class ConstructorFactory: 531 class ConstructorFactory:
470 def create(self, bridge_template, options): 532 def create(self, bridge_template, options):
471 if options.protocole=='dbus': 533 if options.protocole=='dbus':
472 return DbusConstructor(bridge_template, options) 534 return DbusConstructor(bridge_template, options)
473 elif options.protocole=='mediawiki': 535 elif options.protocole=='mediawiki':
474 return MediawikiConstructor(bridge_template, options) 536 return MediawikiConstructor(bridge_template, options)
537 elif options.protocole=='dbus-xml':
538 return DbusXmlConstructor(bridge_template, options)
475 539
476 raise ConstructorError('Unknown constructor type') 540 raise ConstructorError('Unknown constructor type')
477 541
478 class BridgeConstructor: 542 class BridgeConstructor:
479 def __init__(self): 543 def __init__(self):