comparison src/bridge/bridge_constructor/bridge_contructor.py @ 273:3b5e856b3a32

Bridge: added mediawiki constructor in bridge constructor, usefull for documentation purpose
author Goffi <goffi@goffi.org>
date Tue, 25 Jan 2011 01:37:02 +0100
parents 0288f97334f2
children a00e87d48213
comparison
equal deleted inserted replaced
272:1d2e0dfe7114 273:3b5e856b3a32
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'] 38 MANAGED_PROTOCOLES=['dbus','mediawiki']
39 DEFAULT_PROTOCOLE='dbus' 39 DEFAULT_PROTOCOLE='dbus'
40 FLAGS=['deprecated']
40 41
41 import sys 42 import sys
42 import os 43 import os
43 from os import path 44 from os import path
44 from optparse import OptionParser 45 from optparse import OptionParser
45 from ConfigParser import SafeConfigParser as Parser 46 from ConfigParser import SafeConfigParser as Parser
46 from ConfigParser import NoOptionError 47 from ConfigParser import NoOptionError
47 import re 48 import re
49 from datetime import datetime
48 50
49 51
50 class ParseError(Exception): 52 class ParseError(Exception):
51 #Used when the signature parsing is going wrong (invalid signature ?) 53 #Used when the signature parsing is going wrong (invalid signature ?)
52 pass 54 pass
76 @return: dict, each key is the integer param number (no key if no default value)""" 78 @return: dict, each key is the integer param number (no key if no default value)"""
77 default_dict={} 79 default_dict={}
78 def_re = re.compile(r"param_(\d+)_default") 80 def_re = re.compile(r"param_(\d+)_default")
79 81
80 for option in self.bridge_template.options(name): 82 for option in self.bridge_template.options(name):
81 if option == 'doc_return':
82 default_dict['return'] = self.bridge_template.get(name, option)
83 continue
84 match = def_re.match(option) 83 match = def_re.match(option)
85 if match: 84 if match:
86 try: 85 try:
87 idx = int(match.group(1)) 86 idx = int(match.group(1))
88 except ValueError: 87 except ValueError:
89 raise ParseError("Invalid value [%s] for parameter number" % match.group(1)) 88 raise ParseError("Invalid value [%s] for parameter number" % match.group(1))
90 default_dict[idx] = self.bridge_template.get(name, option) 89 default_dict[idx] = self.bridge_template.get(name, option)
91 90
92 return default_dict 91 return default_dict
93 92
93 def getFlags(self, name):
94 """Return list of flags set for this function
95 @param name: Name of the function to get
96 @return: List of flags (string)"""
97 flags=[]
98 for option in self.bridge_template.options(name):
99 if option in FLAGS:
100 flags.append(option)
101 return flags
102
94 def getArgumentsDoc(self, name): 103 def getArgumentsDoc(self, name):
95 """Return documentation of arguments 104 """Return documentation of arguments
96 @param name: Name of the function to get 105 @param name: Name of the function to get
97 @return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)""" 106 @return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)"""
98 doc_dict={} 107 doc_dict={}
99 option_re = re.compile(r"doc_param_(\d+)") 108 option_re = re.compile(r"doc_param_(\d+)")
100 value_re = re.compile(r"^(\w+): (.*)$", re.MULTILINE | re.DOTALL) 109 value_re = re.compile(r"^(\w+): (.*)$", re.MULTILINE | re.DOTALL)
101 for option in self.bridge_template.options(name): 110 for option in self.bridge_template.options(name):
111 if option == 'doc_return':
112 doc_dict['return'] = self.bridge_template.get(name, option)
113 continue
102 match = option_re.match(option) 114 match = option_re.match(option)
103 if match: 115 if match:
104 try: 116 try:
105 idx = int(match.group(1)) 117 idx = int(match.group(1))
106 except ValueError: 118 except ValueError:
108 value_match = value_re.match(self.bridge_template.get(name, option)) 120 value_match = value_re.match(self.bridge_template.get(name, option))
109 if not value_match: 121 if not value_match:
110 raise ParseError("Invalid value for parameter doc [%i]" % idx) 122 raise ParseError("Invalid value for parameter doc [%i]" % idx)
111 doc_dict[idx]=(value_match.group(1),value_match.group(2)) 123 doc_dict[idx]=(value_match.group(1),value_match.group(2))
112 return doc_dict 124 return doc_dict
125
126 def getDoc(self, name):
127 """Return documentation of the method
128 @param name: Name of the function to get
129 @return: string documentation, or None"""
130 if self.bridge_template.has_option(name, "doc"):
131 return self.bridge_template.get(name, "doc")
132 return None
113 133
114 def getArguments(self, signature, name=None, default=None, unicode_protect=False): 134 def getArguments(self, signature, name=None, default=None, unicode_protect=False):
115 """Return arguments to user given a signature 135 """Return arguments to user given a signature
116 @param signature: signature in the short form (using s,a,i,b etc) 136 @param signature: signature in the short form (using s,a,i,b etc)
117 @param name: dictionary of arguments name like given by getArguments 137 @param name: dictionary of arguments name like given by getArguments
182 print ("Can't open destination file [%s]" % full_path) 202 print ("Can't open destination file [%s]" % full_path)
183 except OSError: 203 except OSError:
184 print("It's not possible to generate the file, check your permissions") 204 print("It's not possible to generate the file, check your permissions")
185 exit(1) 205 exit(1)
186 206
207 class MediawikiConstructor(Constructor):
208
209 def __init__(self, bridge_template, options):
210 Constructor.__init__(self, bridge_template, options)
211 self.core_template="mediawiki_template.tpl"
212 self.core_dest="mediawiki.wiki"
213
214 def _wikiParameter(self, name, sig_in):
215 """Format parameters with the wiki syntax
216 @param name: name of the function
217 @param sig_in: signature in
218 @return: string of the formated parameters"""
219 arg_doc = self.getArgumentsDoc(name)
220 arg_default = self.getDefault(name)
221 args_str = self.getArguments(sig_in)
222 args = args_str.split(', ') if args_str else [] #ugly but it works :)
223 wiki=[]
224 for i in range(len(args)):
225 if arg_doc.has_key(i):
226 name,doc=arg_doc[i]
227 doc='\n:'.join(doc.rstrip('\n').split('\n'))
228 wiki.append("; %s: %s" % (name, doc))
229 else:
230 wiki.append("; arg_%d: " % i)
231 if arg_default.has_key(i):
232 wiki.append(":''DEFAULT: %s''" % arg_default[i])
233 return "\n".join(wiki)
234
235 def _wikiReturn(self, name):
236 """Format return doc with the wiki syntax
237 @param name: name of the function
238 """
239 arg_doc = self.getArgumentsDoc(name)
240 wiki=[]
241 if arg_doc.has_key('return'):
242 wiki.append('\n|-\n! scope=row | return value\n|')
243 wiki.append('<br />\n'.join(arg_doc['return'].rstrip('\n').split('\n')))
244 return "\n".join(wiki)
245
246 def generateCoreSide(self):
247 signals_part = []
248 methods_part = []
249 sections = self.bridge_template.sections()
250 sections.sort()
251 for section in sections:
252 function = self.getValues(section)
253 print ("Adding %s %s" % (section, function["type"]))
254 default = self.getDefault(section)
255 deprecated_msg = """<br />'''<font color="#FF0000">/!\ WARNING /!\ : This method is deprecated, please don't use it !</font>'''"""
256 signature_signal = \
257 """\
258 ! scope=row | signature
259 | %s
260 |-\
261 """ % function['sig_in']
262 signature_method = \
263 """\
264 ! scope=row | signature in
265 | %s
266 |-
267 ! scope=row | signature out
268 | %s
269 |-\
270 """ % (function['sig_in'], function['sig_out'])
271 completion = {
272 'signature':signature_signal if function['type']=="signal" else signature_method,
273 'sig_out':function['sig_out'] or '',
274 'category':function['category'],
275 'name':section,
276 'doc':self.getDoc(section) or "FIXME: No description available",
277 'deprecated':deprecated_msg if "deprecated" in self.getFlags(section) else "",
278 'parameters':self._wikiParameter(section, function['sig_in']),
279 'return':self._wikiReturn(section) if function['type'] == 'method' else ''
280 }
281
282 dest = signals_part if function['type'] == "signal" else methods_part
283 dest.append("""\
284 == %(name)s ==
285 ''%(doc)s''
286 %(deprecated)s
287 {| class="wikitable" style="text-align:left; width:80%%;"
288 ! scope=row | category
289 | %(category)s
290 |-
291 %(signature)s
292 ! scope=row | parameters
293 |
294 %(parameters)s%(return)s
295 |}
296 """ % completion)
297
298 #at this point, signals_part, and methods_part should be filled,
299 #we just have to place them in the right part of the template
300 core_bridge = []
301 try:
302 with open(self.core_template) as core_template:
303 for line in core_template:
304 if line.startswith('##SIGNALS_PART##'):
305 core_bridge.extend(signals_part)
306 elif line.startswith('##METHODS_PART##'):
307 core_bridge.extend(methods_part)
308 elif line.startswith('##TIMESTAMP##'):
309 core_bridge.append('Generated on %s' % datetime.now())
310 else:
311 core_bridge.append(line.replace('\n',''))
312 except IOError:
313 print ("Can't open template file [%s]" % self.core_template)
314 sys.exit(1)
315
316 #now we write to final file
317 self.finalWrite(self.core_dest, core_bridge)
318
187 class DbusConstructor(Constructor): 319 class DbusConstructor(Constructor):
188 320
189 def __init__(self, bridge_template, options): 321 def __init__(self, bridge_template, options):
190 Constructor.__init__(self, bridge_template, options) 322 Constructor.__init__(self, bridge_template, options)
191 self.core_template="dbus_core_template.py" 323 self.core_template="dbus_core_template.py"
303 435
304 class ConstructorFactory: 436 class ConstructorFactory:
305 def create(self, bridge_template, options): 437 def create(self, bridge_template, options):
306 if options.protocole=='dbus': 438 if options.protocole=='dbus':
307 return DbusConstructor(bridge_template, options) 439 return DbusConstructor(bridge_template, options)
440 elif options.protocole=='mediawiki':
441 return MediawikiConstructor(bridge_template, options)
308 442
309 raise ConstructorError('Unknown constructor type') 443 raise ConstructorError('Unknown constructor type')
310 444
311 class BridgeConstructor: 445 class BridgeConstructor:
312 def __init__(self): 446 def __init__(self):