comparison src/bridge/bridge_constructor/bridge_contructor.py @ 595:1f160467f5de

Fix pep8 support in src/bridge.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 18 Jan 2013 17:55:35 +0100
parents beaf6bec2fcd
children 84a6e83157c2
comparison
equal deleted inserted replaced
594:e629371a28d3 595:1f160467f5de
17 17
18 You should have received a copy of the GNU Affero General Public License 18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """ 20 """
21 21
22
23 #consts 22 #consts
24 NAME = u"bridge_constructor" 23 NAME = u"bridge_constructor"
25 VERSION="0.1.0" 24 VERSION = "0.1.0"
26 DEST_DIR="generated" 25 DEST_DIR = "generated"
27 ABOUT = NAME+u""" v%s (c) Jérôme Poisson (aka Goffi) 2011 26 ABOUT = NAME + u""" v%s (c) Jérôme Poisson (aka Goffi) 2011
28 27
29 --- 28 ---
30 """+NAME+u""" Copyright (C) 2011 Jérôme Poisson (aka Goffi) 29 """ + NAME + u""" Copyright (C) 2011 Jérôme Poisson (aka Goffi)
31 This program comes with ABSOLUTELY NO WARRANTY; 30 This program comes with ABSOLUTELY NO WARRANTY;
32 This is free software, and you are welcome to redistribute it 31 This is free software, and you are welcome to redistribute it
33 under certain conditions. 32 under certain conditions.
34 --- 33 ---
35 34
36 This script construct a SàT bridge using the given protocol 35 This script construct a SàT bridge using the given protocol
37 """ 36 """
38 MANAGED_PROTOCOLES=['dbus','mediawiki', 'dbus-xml'] 37 MANAGED_PROTOCOLES = ['dbus', 'mediawiki', 'dbus-xml']
39 DEFAULT_PROTOCOLE='dbus' 38 DEFAULT_PROTOCOLE = 'dbus'
40 FLAGS=['deprecated', 'async'] 39 FLAGS = ['deprecated', 'async']
41 40
42 ENV_OVERRIDE = "SAT_BRIDGE_CONST_" #Prefix used to override a constant 41 ENV_OVERRIDE = "SAT_BRIDGE_CONST_" # Prefix used to override a constant
43 42
44 import sys 43 import sys
45 import os 44 import os
46 from os import path 45 from os import path
47 from optparse import OptionParser 46 from optparse import OptionParser
54 53
55 class ParseError(Exception): 54 class ParseError(Exception):
56 #Used when the signature parsing is going wrong (invalid signature ?) 55 #Used when the signature parsing is going wrong (invalid signature ?)
57 pass 56 pass
58 57
58
59 class Constructor(object): 59 class Constructor(object):
60 60
61 def __init__(self, bridge_template, options): 61 def __init__(self, bridge_template, options):
62 self.bridge_template = bridge_template 62 self.bridge_template = bridge_template
63 self.options = options 63 self.options = options
64 64
65 def getValues(self, name): 65 def getValues(self, name):
66 """Return values of a function in a dict 66 """Return values of a function in a dict
67 @param name: Name of the function to get 67 @param name: Name of the function to get
68 @return: dict, each key has the config value or None if the value is not set""" 68 @return: dict, each key has the config value or None if the value is not set"""
69 function={} 69 function = {}
70 for option in ['type','category','sig_in','sig_out','doc']: 70 for option in ['type', 'category', 'sig_in', 'sig_out', 'doc']:
71 try: 71 try:
72 value = self.bridge_template.get(name, option) 72 value = self.bridge_template.get(name, option)
73 except NoOptionError: 73 except NoOptionError:
74 value = None 74 value = None
75 function[option] = value 75 function[option] = value
77 77
78 def getDefault(self, name): 78 def getDefault(self, name):
79 """Return default values of a function in a dict 79 """Return default values of a function in a dict
80 @param name: Name of the function to get 80 @param name: Name of the function to get
81 @return: dict, each key is the integer param number (no key if no default value)""" 81 @return: dict, each key is the integer param number (no key if no default value)"""
82 default_dict={} 82 default_dict = {}
83 def_re = re.compile(r"param_(\d+)_default") 83 def_re = re.compile(r"param_(\d+)_default")
84 84
85 for option in self.bridge_template.options(name): 85 for option in self.bridge_template.options(name):
86 match = def_re.match(option) 86 match = def_re.match(option)
87 if match: 87 if match:
95 95
96 def getFlags(self, name): 96 def getFlags(self, name):
97 """Return list of flags set for this function 97 """Return list of flags set for this function
98 @param name: Name of the function to get 98 @param name: Name of the function to get
99 @return: List of flags (string)""" 99 @return: List of flags (string)"""
100 flags=[] 100 flags = []
101 for option in self.bridge_template.options(name): 101 for option in self.bridge_template.options(name):
102 if option in FLAGS: 102 if option in FLAGS:
103 flags.append(option) 103 flags.append(option)
104 return flags 104 return flags
105 105
106 def getArgumentsDoc(self, name): 106 def getArgumentsDoc(self, name):
107 """Return documentation of arguments 107 """Return documentation of arguments
108 @param name: Name of the function to get 108 @param name: Name of the function to get
109 @return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)""" 109 @return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)"""
110 doc_dict={} 110 doc_dict = {}
111 option_re = re.compile(r"doc_param_(\d+)") 111 option_re = re.compile(r"doc_param_(\d+)")
112 value_re = re.compile(r"^(\w+): (.*)$", re.MULTILINE | re.DOTALL) 112 value_re = re.compile(r"^(\w+): (.*)$", re.MULTILINE | re.DOTALL)
113 for option in self.bridge_template.options(name): 113 for option in self.bridge_template.options(name):
114 if option == 'doc_return': 114 if option == 'doc_return':
115 doc_dict['return'] = self.bridge_template.get(name, option) 115 doc_dict['return'] = self.bridge_template.get(name, option)
121 except ValueError: 121 except ValueError:
122 raise ParseError("Invalid value [%s] for parameter number" % match.group(1)) 122 raise ParseError("Invalid value [%s] for parameter number" % match.group(1))
123 value_match = value_re.match(self.bridge_template.get(name, option)) 123 value_match = value_re.match(self.bridge_template.get(name, option))
124 if not value_match: 124 if not value_match:
125 raise ParseError("Invalid value for parameter doc [%i]" % idx) 125 raise ParseError("Invalid value for parameter doc [%i]" % idx)
126 doc_dict[idx]=(value_match.group(1),value_match.group(2)) 126 doc_dict[idx] = (value_match.group(1), value_match.group(2))
127 return doc_dict 127 return doc_dict
128 128
129 def getDoc(self, name): 129 def getDoc(self, name):
130 """Return documentation of the method 130 """Return documentation of the method
131 @param name: Name of the function to get 131 @param name: Name of the function to get
132 @return: string documentation, or None""" 132 @return: string documentation, or None"""
133 if self.bridge_template.has_option(name, "doc"): 133 if self.bridge_template.has_option(name, "doc"):
134 return self.bridge_template.get(name, "doc") 134 return self.bridge_template.get(name, "doc")
135 return None 135 return None
136 136
137
138 def argumentsParser(self, signature): 137 def argumentsParser(self, signature):
139 """Generator which return individual arguments signatures from a global signature""" 138 """Generator which return individual arguments signatures from a global signature"""
140 start=0 139 start = 0
141 i=0 140 i = 0
142 141
143 while i<len(signature): 142 while i < len(signature):
144 if signature[i] not in ['b','y','n','i','x','q','u','t','d','s','a']: 143 if signature[i] not in ['b', 'y', 'n', 'i', 'x', 'q', 'u', 't', 'd', 's', 'a']:
145 raise ParseError("Unmanaged attribute type [%c]" % signature[i]) 144 raise ParseError("Unmanaged attribute type [%c]" % signature[i])
146 145
147 if signature[i] == 'a': 146 if signature[i] == 'a':
148 i+=1 147 i += 1
149 if signature[i]!='{' and signature[i]!='(': #FIXME: must manage tuples out of arrays 148 if signature[i] != '{' and signature[i] != '(': # FIXME: must manage tuples out of arrays
150 i+=1 149 i += 1
151 yield signature[start:i] 150 yield signature[start:i]
152 start=i 151 start = i
153 continue #we have a simple type for the array 152 continue # we have a simple type for the array
154 opening_car = signature[i] 153 opening_car = signature[i]
155 assert(opening_car in ['{','(']) 154 assert(opening_car in ['{', '('])
156 closing_car = '}' if opening_car == '{' else ')' 155 closing_car = '}' if opening_car == '{' else ')'
157 opening_count = 1 156 opening_count = 1
158 while (True): #we have a dict or a list of tuples 157 while (True): # we have a dict or a list of tuples
159 i+=1 158 i += 1
160 if i>=len(signature): 159 if i >= len(signature):
161 raise ParseError("missing }") 160 raise ParseError("missing }")
162 if signature[i] == opening_car: 161 if signature[i] == opening_car:
163 opening_count+=1 162 opening_count += 1
164 if signature[i] == closing_car: 163 if signature[i] == closing_car:
165 opening_count-=1 164 opening_count -= 1
166 if opening_count == 0: 165 if opening_count == 0:
167 break 166 break
168 i+=1 167 i += 1
169 yield signature[start:i] 168 yield signature[start:i]
170 start=i 169 start = i
171 170
172 def getArguments(self, signature, name=None, default=None, unicode_protect=False): 171 def getArguments(self, signature, name=None, default=None, unicode_protect=False):
173 """Return arguments to user given a signature 172 """Return arguments to user given a signature
174 @param signature: signature in the short form (using s,a,i,b etc) 173 @param signature: signature in the short form (using s,a,i,b etc)
175 @param name: dictionary of arguments name like given by getArguments 174 @param name: dictionary of arguments name like given by getArguments
176 @param default: dictionary of default values, like given by getDefault 175 @param default: dictionary of default values, like given by getDefault
177 @param unicode_protect: activate unicode protection on strings (return strings as unicode(str)) 176 @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")""" 177 @return: list of arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")"""
179 idx=0 178 idx = 0
180 attr_string=[] 179 attr_string = []
181 180
182 for arg in self.argumentsParser(signature): 181 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") % { 182 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, 183 'name': name[idx][0] if (name and idx in name) else "arg_%i" % idx,
185 'default':"="+default[idx] if (default and default.has_key(idx)) else '' 184 'default': "=" + default[idx] if (default and idx in default) else ''})
186 }) #give arg_1, arg2, etc or name1, name2=default, etc. \ 185 # 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 186 #give unicode(arg_1), unicode(arg_2), etc. if unicode_protect is set and arg is a string
188 idx+=1 187 idx += 1
189 188
190 return ", ".join(attr_string) 189 return ", ".join(attr_string)
191 190
192 def generateCoreSide(self): 191 def generateCoreSide(self):
193 """create the constructor in SàT core side (backend)""" 192 """create the constructor in SàT core side (backend)"""
205 print ("The destination dir [%s] can't be created: a file with this name already exists !") 204 print ("The destination dir [%s] can't be created: a file with this name already exists !")
206 sys.exit(1) 205 sys.exit(1)
207 try: 206 try:
208 if not os.path.exists(DEST_DIR): 207 if not os.path.exists(DEST_DIR):
209 os.mkdir(DEST_DIR) 208 os.mkdir(DEST_DIR)
210 full_path=os.path.join(DEST_DIR,filename) 209 full_path = os.path.join(DEST_DIR, filename)
211 if os.path.exists(full_path) and not self.options.force: 210 if os.path.exists(full_path) and not self.options.force:
212 print ("The destination file [%s] already exists ! Use --force to overwrite it" % full_path) 211 print ("The destination file [%s] already exists ! Use --force to overwrite it" % full_path)
213 try: 212 try:
214 with open(full_path,'w') as dest_file: 213 with open(full_path, 'w') as dest_file:
215 dest_file.write('\n'.join(file_buf)) 214 dest_file.write('\n'.join(file_buf))
216 except IOError: 215 except IOError:
217 print ("Can't open destination file [%s]" % full_path) 216 print ("Can't open destination file [%s]" % full_path)
218 except OSError: 217 except OSError:
219 print("It's not possible to generate the file, check your permissions") 218 print("It's not possible to generate the file, check your permissions")
220 exit(1) 219 exit(1)
221 220
221
222 class MediawikiConstructor(Constructor): 222 class MediawikiConstructor(Constructor):
223 223
224 def __init__(self, bridge_template, options): 224 def __init__(self, bridge_template, options):
225 Constructor.__init__(self, bridge_template, options) 225 Constructor.__init__(self, bridge_template, options)
226 self.core_template="mediawiki_template.tpl" 226 self.core_template = "mediawiki_template.tpl"
227 self.core_dest="mediawiki.wiki" 227 self.core_dest = "mediawiki.wiki"
228 228
229 def _addTextDecorations(self, text): 229 def _addTextDecorations(self, text):
230 """Add text decorations like coloration or shortcuts""" 230 """Add text decorations like coloration or shortcuts"""
231 231
232 def anchor_link(match): 232 def anchor_link(match):
245 @param sig_in: signature in 245 @param sig_in: signature in
246 @return: string of the formated parameters""" 246 @return: string of the formated parameters"""
247 arg_doc = self.getArgumentsDoc(name) 247 arg_doc = self.getArgumentsDoc(name)
248 arg_default = self.getDefault(name) 248 arg_default = self.getDefault(name)
249 args_str = self.getArguments(sig_in) 249 args_str = self.getArguments(sig_in)
250 args = args_str.split(', ') if args_str else [] #ugly but it works :) 250 args = args_str.split(', ') if args_str else [] # ugly but it works :)
251 wiki=[] 251 wiki = []
252 for i in range(len(args)): 252 for i in range(len(args)):
253 if arg_doc.has_key(i): 253 if i in arg_doc:
254 name,doc=arg_doc[i] 254 name, doc = arg_doc[i]
255 doc='\n:'.join(doc.rstrip('\n').split('\n')) 255 doc = '\n:'.join(doc.rstrip('\n').split('\n'))
256 wiki.append("; %s: %s" % (name, self._addTextDecorations(doc))) 256 wiki.append("; %s: %s" % (name, self._addTextDecorations(doc)))
257 else: 257 else:
258 wiki.append("; arg_%d: " % i) 258 wiki.append("; arg_%d: " % i)
259 if arg_default.has_key(i): 259 if i in arg_default:
260 wiki.append(":''DEFAULT: %s''" % arg_default[i]) 260 wiki.append(":''DEFAULT: %s''" % arg_default[i])
261 return "\n".join(wiki) 261 return "\n".join(wiki)
262 262
263 def _wikiReturn(self, name): 263 def _wikiReturn(self, name):
264 """Format return doc with the wiki syntax 264 """Format return doc with the wiki syntax
265 @param name: name of the function 265 @param name: name of the function
266 """ 266 """
267 arg_doc = self.getArgumentsDoc(name) 267 arg_doc = self.getArgumentsDoc(name)
268 wiki=[] 268 wiki = []
269 if arg_doc.has_key('return'): 269 if 'return' in arg_doc:
270 wiki.append('\n|-\n! scope=row | return value\n|') 270 wiki.append('\n|-\n! scope=row | return value\n|')
271 wiki.append('<br />\n'.join(self._addTextDecorations(arg_doc['return']).rstrip('\n').split('\n'))) 271 wiki.append('<br />\n'.join(self._addTextDecorations(arg_doc['return']).rstrip('\n').split('\n')))
272 return "\n".join(wiki) 272 return "\n".join(wiki)
273 273
274 def generateCoreSide(self): 274 def generateCoreSide(self):
281 print ("Adding %s %s" % (section, function["type"])) 281 print ("Adding %s %s" % (section, function["type"]))
282 default = self.getDefault(section) 282 default = self.getDefault(section)
283 async_msg = """<br />'''This method is asynchronous'''""" 283 async_msg = """<br />'''This method is asynchronous'''"""
284 deprecated_msg = """<br />'''<font color="#FF0000">/!\ WARNING /!\ : This method is deprecated, please don't use it !</font>'''""" 284 deprecated_msg = """<br />'''<font color="#FF0000">/!\ WARNING /!\ : This method is deprecated, please don't use it !</font>'''"""
285 signature_signal = \ 285 signature_signal = \
286 """\ 286 """\
287 ! scope=row | signature 287 ! scope=row | signature
288 | %s 288 | %s
289 |-\ 289 |-\
290 """ % function['sig_in'] 290 """ % function['sig_in']
291 signature_method = \ 291 signature_method = \
292 """\ 292 """\
293 ! scope=row | signature in 293 ! scope=row | signature in
294 | %s 294 | %s
295 |- 295 |-
296 ! scope=row | signature out 296 ! scope=row | signature out
297 | %s 297 | %s
298 |-\ 298 |-\
299 """ % (function['sig_in'], function['sig_out']) 299 """ % (function['sig_in'], function['sig_out'])
300 completion = { 300 completion = {
301 'signature':signature_signal if function['type']=="signal" else signature_method, 301 'signature': signature_signal if function['type'] == "signal" else signature_method,
302 'sig_out':function['sig_out'] or '', 302 'sig_out': function['sig_out'] or '',
303 'category':function['category'], 303 'category': function['category'],
304 'name':section, 304 'name': section,
305 'doc':self.getDoc(section) or "FIXME: No description available", 305 'doc': self.getDoc(section) or "FIXME: No description available",
306 'async':async_msg if "async" in self.getFlags(section) else "", 306 'async': async_msg if "async" in self.getFlags(section) else "",
307 'deprecated':deprecated_msg if "deprecated" in self.getFlags(section) else "", 307 'deprecated': deprecated_msg if "deprecated" in self.getFlags(section) else "",
308 'parameters':self._wikiParameter(section, function['sig_in']), 308 'parameters': self._wikiParameter(section, function['sig_in']),
309 'return':self._wikiReturn(section) if function['type'] == 'method' else '' 309 'return': self._wikiReturn(section) if function['type'] == 'method' else ''}
310 }
311 310
312 dest = signals_part if function['type'] == "signal" else methods_part 311 dest = signals_part if function['type'] == "signal" else methods_part
313 dest.append("""\ 312 dest.append("""\
314 == %(name)s == 313 == %(name)s ==
315 ''%(doc)s'' 314 ''%(doc)s''
337 elif line.startswith('##METHODS_PART##'): 336 elif line.startswith('##METHODS_PART##'):
338 core_bridge.extend(methods_part) 337 core_bridge.extend(methods_part)
339 elif line.startswith('##TIMESTAMP##'): 338 elif line.startswith('##TIMESTAMP##'):
340 core_bridge.append('Generated on %s' % datetime.now()) 339 core_bridge.append('Generated on %s' % datetime.now())
341 else: 340 else:
342 core_bridge.append(line.replace('\n','')) 341 core_bridge.append(line.replace('\n', ''))
343 except IOError: 342 except IOError:
344 print ("Can't open template file [%s]" % self.core_template) 343 print ("Can't open template file [%s]" % self.core_template)
345 sys.exit(1) 344 sys.exit(1)
346 345
347 #now we write to final file 346 #now we write to final file
348 self.finalWrite(self.core_dest, core_bridge) 347 self.finalWrite(self.core_dest, core_bridge)
349 348
349
350 class DbusConstructor(Constructor): 350 class DbusConstructor(Constructor):
351 351
352 def __init__(self, bridge_template, options): 352 def __init__(self, bridge_template, options):
353 Constructor.__init__(self, bridge_template, options) 353 Constructor.__init__(self, bridge_template, options)
354 self.core_template="dbus_core_template.py" 354 self.core_template = "dbus_core_template.py"
355 self.frontend_template="dbus_frontend_template.py" 355 self.frontend_template = "dbus_frontend_template.py"
356 self.frontend_dest = self.core_dest="DBus.py" 356 self.frontend_dest = self.core_dest = "DBus.py"
357 357
358 def generateCoreSide(self): 358 def generateCoreSide(self):
359 signals_part = [] 359 signals_part = []
360 methods_part = [] 360 methods_part = []
361 direct_calls = [] 361 direct_calls = []
366 print ("Adding %s %s" % (section, function["type"])) 366 print ("Adding %s %s" % (section, function["type"]))
367 default = self.getDefault(section) 367 default = self.getDefault(section)
368 arg_doc = self.getArgumentsDoc(section) 368 arg_doc = self.getArgumentsDoc(section)
369 async = "async" in self.getFlags(section) 369 async = "async" in self.getFlags(section)
370 completion = { 370 completion = {
371 'sig_in':function['sig_in'] or '', 371 'sig_in': function['sig_in'] or '',
372 'sig_out':function['sig_out'] or '', 372 'sig_out': function['sig_out'] or '',
373 'category':'PLUGIN' if function['category'] == 'plugin' else 'CORE', 373 'category': 'PLUGIN' if function['category'] == 'plugin' else 'CORE',
374 'name':section, 374 'name': section,
375 'args':self.getArguments(function['sig_in'], name=arg_doc, default=default ) 375 'args': self.getArguments(function['sig_in'], name=arg_doc, default=default)}
376 }
377 376
378 if function["type"] == "signal": 377 if function["type"] == "signal":
379 completion['body'] = "pass" if not self.options.debug else 'debug ("%s")' % section 378 completion['body'] = "pass" if not self.options.debug else 'debug ("%s")' % section
380 signals_part.append("""\ 379 signals_part.append("""\
381 @dbus.service.signal(const_INT_PREFIX+const_%(category)s_SUFFIX, 380 @dbus.service.signal(const_INT_PREFIX+const_%(category)s_SUFFIX,
387 def %(name)s(self, %(args)s): 386 def %(name)s(self, %(args)s):
388 self.dbus_bridge.%(name)s(%(args)s) 387 self.dbus_bridge.%(name)s(%(args)s)
389 """ % completion) 388 """ % completion)
390 389
391 elif function["type"] == "method": 390 elif function["type"] == "method":
392 completion['debug'] = "" if not self.options.debug else 'debug ("%s")\n%s' % (section,8*' ') 391 completion['debug'] = "" if not self.options.debug else 'debug ("%s")\n%s' % (section, 8 * ' ')
393 completion['args_result'] = self.getArguments(function['sig_in'], name=arg_doc, unicode_protect=self.options.unicode) 392 completion['args_result'] = self.getArguments(function['sig_in'], name=arg_doc, unicode_protect=self.options.unicode)
394 completion['async_comma'] = ', ' if async and function['sig_in'] else '' 393 completion['async_comma'] = ', ' if async and function['sig_in'] else ''
395 completion['async_args_def'] = 'callback=None, errback=None' if async else '' 394 completion['async_args_def'] = 'callback=None, errback=None' if async else ''
396 completion['async_args_call'] = 'callback=callback, errback=errback' if async else '' 395 completion['async_args_call'] = 'callback=callback, errback=errback' if async else ''
397 completion['async_callbacks'] = "('callback', 'errback')" if async else "None" 396 completion['async_callbacks'] = "('callback', 'errback')" if async else "None"
420 else: 419 else:
421 if line.startswith('const_'): 420 if line.startswith('const_'):
422 const_name = line[len('const_'):line.find(' = ')] 421 const_name = line[len('const_'):line.find(' = ')]
423 if const_name in const_override: 422 if const_name in const_override:
424 print ("const %s overriden" % const_name) 423 print ("const %s overriden" % const_name)
425 core_bridge.append('const_%s = %s' % (const_name, os.environ[ENV_OVERRIDE+const_name])) 424 core_bridge.append('const_%s = %s' % (const_name, os.environ[ENV_OVERRIDE + const_name]))
426 continue 425 continue
427 core_bridge.append(line.replace('\n','')) 426 core_bridge.append(line.replace('\n', ''))
428 except IOError: 427 except IOError:
429 print ("Can't open template file [%s]" % self.core_template) 428 print ("Can't open template file [%s]" % self.core_template)
430 sys.exit(1) 429 sys.exit(1)
431 430
432 #now we write to final file 431 #now we write to final file
441 print ("Adding %s %s" % (section, function["type"])) 440 print ("Adding %s %s" % (section, function["type"]))
442 default = self.getDefault(section) 441 default = self.getDefault(section)
443 arg_doc = self.getArgumentsDoc(section) 442 arg_doc = self.getArgumentsDoc(section)
444 async = "async" in self.getFlags(section) 443 async = "async" in self.getFlags(section)
445 completion = { 444 completion = {
446 'sig_in':function['sig_in'] or '', 445 'sig_in': function['sig_in'] or '',
447 'sig_out':function['sig_out'] or '', 446 'sig_out': function['sig_out'] or '',
448 'category':'plugin' if function['category'] == 'plugin' else 'core', 447 'category': 'plugin' if function['category'] == 'plugin' else 'core',
449 'name':section, 448 'name': section,
450 'args':self.getArguments(function['sig_in'], name=arg_doc, default=default) 449 'args': self.getArguments(function['sig_in'], name=arg_doc, default=default)}
451 }
452 450
453 if function["type"] == "method": 451 if function["type"] == "method":
454 completion['debug'] = "" if not self.options.debug else 'debug ("%s")\n%s' % (section,8*' ') 452 completion['debug'] = "" if not self.options.debug else 'debug ("%s")\n%s' % (section, 8 * ' ')
455 completion['args_result'] = self.getArguments(function['sig_in'], name=arg_doc) 453 completion['args_result'] = self.getArguments(function['sig_in'], name=arg_doc)
456 completion['async_args'] = ', callback=None, errback=None' if async else '' 454 completion['async_args'] = ', callback=None, errback=None' if async else ''
457 completion['async_comma'] = ', ' if async and function['sig_in'] else '' 455 completion['async_comma'] = ', ' if async and function['sig_in'] else ''
458 completion['async_args_result'] = 'reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])' if async else '' 456 completion['async_args_result'] = 'reply_handler=callback, error_handler=lambda err:errback(err._dbus_error_name[len(const_ERROR_PREFIX)+1:])' if async else ''
459 result = "self.db_%(category)s_iface.%(name)s(%(args_result)s%(async_comma)s%(async_args_result)s)" % completion 457 result = "self.db_%(category)s_iface.%(name)s(%(args_result)s%(async_comma)s%(async_args_result)s)" % completion
476 else: 474 else:
477 if line.startswith('const_'): 475 if line.startswith('const_'):
478 const_name = line[len('const_'):line.find(' = ')] 476 const_name = line[len('const_'):line.find(' = ')]
479 if const_name in const_override: 477 if const_name in const_override:
480 print ("const %s overriden" % const_name) 478 print ("const %s overriden" % const_name)
481 frontend_bridge.append('const_%s = %s' % (const_name, os.environ[ENV_OVERRIDE+const_name])) 479 frontend_bridge.append('const_%s = %s' % (const_name, os.environ[ENV_OVERRIDE + const_name]))
482 continue 480 continue
483 frontend_bridge.append(line.replace('\n','')) 481 frontend_bridge.append(line.replace('\n', ''))
484 except IOError: 482 except IOError:
485 print ("Can't open template file [%s]" % self.frontend_template) 483 print ("Can't open template file [%s]" % self.frontend_template)
486 sys.exit(1) 484 sys.exit(1)
487 485
488 #now we write to final file 486 #now we write to final file
489 self.finalWrite(self.frontend_dest, frontend_bridge) 487 self.finalWrite(self.frontend_dest, frontend_bridge)
490 488
489
491 class DbusXmlConstructor(Constructor): 490 class DbusXmlConstructor(Constructor):
492 """Constructor for DBus XML syntaxt (used by Qt frontend)""" 491 """Constructor for DBus XML syntaxt (used by Qt frontend)"""
493 492
494 def __init__(self, bridge_template, options): 493 def __init__(self, bridge_template, options):
495 Constructor.__init__(self, bridge_template, options) 494 Constructor.__init__(self, bridge_template, options)
496 495
497 self.template="dbus_xml_template.xml" 496 self.template = "dbus_xml_template.xml"
498 self.core_dest="org.goffi.sat.xml" 497 self.core_dest = "org.goffi.sat.xml"
499 self.default_annotation = { 'a{ss}': 'StringDict', 498 self.default_annotation = {'a{ss}': 'StringDict',
500 'a(sa{ss}as)': 'QList<Contact>', 499 'a(sa{ss}as)': 'QList<Contact>',
501 'a{i(ss)}': 'HistoryT', 500 'a{i(ss)}': 'HistoryT',
502 'a(sss)': 'QList<MenuT>', 501 'a(sss)': 'QList<MenuT>',
503 'a{sa{s(sia{ss})}}': 'PresenceStatusT', 502 'a{sa{s(sia{ss})}}': 'PresenceStatusT',
504 'a{sa{ss}}': 'ActionResultExtDataT', 503 'a{sa{ss}}': 'ActionResultExtDataT'}
505 }
506 504
507 def generateCoreSide(self): 505 def generateCoreSide(self):
508 try: 506 try:
509 doc = minidom.parse(self.template) 507 doc = minidom.parse(self.template)
510 interface_elt = doc.getElementsByTagName('interface')[0] 508 interface_elt = doc.getElementsByTagName('interface')[0]
518 sections = self.bridge_template.sections() 516 sections = self.bridge_template.sections()
519 sections.sort() 517 sections.sort()
520 for section in sections: 518 for section in sections:
521 function = self.getValues(section) 519 function = self.getValues(section)
522 print ("Adding %s %s" % (section, function["type"])) 520 print ("Adding %s %s" % (section, function["type"]))
523 new_elt = doc.createElement('method' if function["type"]=='method' else 'signal') 521 new_elt = doc.createElement('method' if function["type"] == 'method' else 'signal')
524 new_elt.setAttribute('name', section) 522 new_elt.setAttribute('name', section)
525 args_in_str = self.getArguments(function['sig_in']) 523 args_in_str = self.getArguments(function['sig_in'])
526 524
527 idx=0 525 idx = 0
528 args_doc = self.getArgumentsDoc(section) 526 args_doc = self.getArgumentsDoc(section)
529 for arg in self.argumentsParser(function['sig_in'] or ''): 527 for arg in self.argumentsParser(function['sig_in'] or ''):
530 arg_elt = doc.createElement('arg') 528 arg_elt = doc.createElement('arg')
531 arg_elt.setAttribute('name', args_doc[idx][0] if args_doc.has_key(idx) else "arg_%i" % idx) 529 arg_elt.setAttribute('name', args_doc[idx][0] if idx in args_doc else "arg_%i" % idx)
532 arg_elt.setAttribute('type', arg) 530 arg_elt.setAttribute('type', arg)
533 _direction = 'in' if function["type"]=='method' else 'out' 531 _direction = 'in' if function["type"] == 'method' else 'out'
534 arg_elt.setAttribute('direction', _direction) 532 arg_elt.setAttribute('direction', _direction)
535 new_elt.appendChild(arg_elt) 533 new_elt.appendChild(arg_elt)
536 if "annotation" in self.options.flags: 534 if "annotation" in self.options.flags:
537 if arg in self.default_annotation: 535 if arg in self.default_annotation:
538 annot_elt = doc.createElement("annotation") 536 annot_elt = doc.createElement("annotation")
539 annot_elt.setAttribute('name', "com.trolltech.QtDBus.QtTypeName.In%d" % idx) 537 annot_elt.setAttribute('name', "com.trolltech.QtDBus.QtTypeName.In%d" % idx)
540 annot_elt.setAttribute('value', self.default_annotation[arg]) 538 annot_elt.setAttribute('value', self.default_annotation[arg])
541 new_elt.appendChild(annot_elt) 539 new_elt.appendChild(annot_elt)
542 idx+=1 540 idx += 1
543 541
544 if function['sig_out']: 542 if function['sig_out']:
545 arg_elt = doc.createElement('arg') 543 arg_elt = doc.createElement('arg')
546 arg_elt.setAttribute('type', function['sig_out']) 544 arg_elt.setAttribute('type', function['sig_out'])
547 arg_elt.setAttribute('direction', 'out') 545 arg_elt.setAttribute('direction', 'out')
556 interface_elt.appendChild(new_elt) 554 interface_elt.appendChild(new_elt)
557 555
558 #now we write to final file 556 #now we write to final file
559 self.finalWrite(self.core_dest, [doc.toprettyxml()]) 557 self.finalWrite(self.core_dest, [doc.toprettyxml()])
560 558
559
561 class ConstructorError(Exception): 560 class ConstructorError(Exception):
562 pass 561 pass
563 562
563
564 class ConstructorFactory(object): 564 class ConstructorFactory(object):
565 def create(self, bridge_template, options): 565 def create(self, bridge_template, options):
566 if options.protocole=='dbus': 566 if options.protocole == 'dbus':
567 return DbusConstructor(bridge_template, options) 567 return DbusConstructor(bridge_template, options)
568 elif options.protocole=='mediawiki': 568 elif options.protocole == 'mediawiki':
569 return MediawikiConstructor(bridge_template, options) 569 return MediawikiConstructor(bridge_template, options)
570 elif options.protocole=='dbus-xml': 570 elif options.protocole == 'dbus-xml':
571 return DbusXmlConstructor(bridge_template, options) 571 return DbusXmlConstructor(bridge_template, options)
572 572
573 raise ConstructorError('Unknown constructor type') 573 raise ConstructorError('Unknown constructor type')
574
574 575
575 class BridgeConstructor(object): 576 class BridgeConstructor(object):
576 def __init__(self): 577 def __init__(self):
577 self.options = None 578 self.options = None
578 579
579 def check_options(self): 580 def check_options(self):
580 """Check command line options""" 581 """Check command line options"""
581 _usage=""" 582 _usage = """
582 %prog [options] 583 %prog [options]
583 584
584 %prog --help for options list 585 %prog --help for options list
585 """ 586 """
586 parser = OptionParser(usage=_usage,version=ABOUT % VERSION) 587 parser = OptionParser(usage=_usage, version=ABOUT % VERSION)
587 588
588 parser.add_option("-p", "--protocole", action="store", type="string", default=DEFAULT_PROTOCOLE, 589 parser.add_option("-p", "--protocole", action="store", type="string", default=DEFAULT_PROTOCOLE,
589 help="Generate bridge using PROTOCOLE (default: %s, possible values: [%s])" % (DEFAULT_PROTOCOLE, ", ".join(MANAGED_PROTOCOLES))) 590 help="Generate bridge using PROTOCOLE (default: %s, possible values: [%s])" % (DEFAULT_PROTOCOLE, ", ".join(MANAGED_PROTOCOLES)))
590 parser.add_option("-s", "--side", action="store", type="string", default="core", 591 parser.add_option("-s", "--side", action="store", type="string", default="core",
591 help="Which side of the bridge do you want to make ? (default: %default, possible values: [core, frontend])") 592 help="Which side of the bridge do you want to make ? (default: %default, possible values: [core, frontend])")
592 parser.add_option("-t", "--template", action="store", type="string", default='bridge_template.ini', 593 parser.add_option("-t", "--template", action="store", type="string", default='bridge_template.ini',
593 help="Use TEMPLATE to generate bridge (default: %default)") 594 help="Use TEMPLATE to generate bridge (default: %default)")
594 parser.add_option("-f", "--force", action="store_true", default=False, 595 parser.add_option("-f", "--force", action="store_true", default=False,
595 help=("Force overwritting of existing files")) 596 help=("Force overwritting of existing files"))
596 parser.add_option("-d", "--debug", action="store_true", default=False, 597 parser.add_option("-d", "--debug", action="store_true", default=False,
597 help=("Add debug information printing")) 598 help=("Add debug information printing"))
598 parser.add_option("--no_unicode", action="store_false", dest="unicode", default=True, 599 parser.add_option("--no_unicode", action="store_false", dest="unicode", default=True,
599 help=("Remove unicode type protection from string results")) 600 help=("Remove unicode type protection from string results"))
600 parser.add_option("--flags", action="store", type="string", 601 parser.add_option("--flags", action="store", type="string",
601 help=("Constructors' specific flags, comma separated")) 602 help=("Constructors' specific flags, comma separated"))
602
603 603
604 (self.options, args) = parser.parse_args() 604 (self.options, args) = parser.parse_args()
605 self.options.flags = self.options.flags.split(',') if self.options.flags else [] 605 self.options.flags = self.options.flags.split(',') if self.options.flags else []
606 return args 606 return args
607 607