comparison src/bridge/bridge_contructor.py @ 266:c4b84a2d2ad1

bridge: constructor and template improved, documentation added
author Goffi <goffi@goffi.org>
date Mon, 24 Jan 2011 17:47:45 +0100
parents b5f1f3dc9ac6
children
comparison
equal deleted inserted replaced
265:b5f1f3dc9ac6 266:c4b84a2d2ad1
39 39
40 import sys 40 import sys
41 import os 41 import os
42 from os import path 42 from os import path
43 from optparse import OptionParser 43 from optparse import OptionParser
44 from ConfigParser import RawConfigParser as Parser 44 from ConfigParser import SafeConfigParser as Parser
45 from ConfigParser import NoOptionError 45 from ConfigParser import NoOptionError
46 import re
46 47
47 48
48 class ParseError(Exception): 49 class ParseError(Exception):
49 #Used when the signature parsing is going wrong (invalid signature ?) 50 #Used when the signature parsing is going wrong (invalid signature ?)
50 pass 51 pass
65 value = self.bridge_template.get(name, option) 66 value = self.bridge_template.get(name, option)
66 except NoOptionError: 67 except NoOptionError:
67 value = None 68 value = None
68 function[option] = value 69 function[option] = value
69 return function 70 return function
70 71
71 def getArguments(self, signature): 72 def getDefault(self, name):
73 """Return default values of a function in a dict
74 @param name: Name of the function to get
75 @return: dict, each key is the integer param number (no key if no default value)"""
76 default_dict={}
77 def_re = re.compile(r"param_(\d+)_default")
78
79 for option in self.bridge_template.options(name):
80 if option == 'doc_return':
81 default_dict['return'] = self.bridge_template.get(name, option)
82 continue
83 match = def_re.match(option)
84 if match:
85 try:
86 idx = int(match.group(1))
87 except ValueError:
88 raise ParseError("Invalid value [%s] for parameter number" % match.group(1))
89 default_dict[idx] = self.bridge_template.get(name, option)
90
91 return default_dict
92
93 def getArgumentsDoc(self, name):
94 """Return documentation of arguments
95 @param name: Name of the function to get
96 @return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)"""
97 doc_dict={}
98 option_re = re.compile(r"doc_param_(\d+)")
99 value_re = re.compile(r"^(\w+): (.*)$", re.MULTILINE | re.DOTALL)
100 for option in self.bridge_template.options(name):
101 match = option_re.match(option)
102 if match:
103 try:
104 idx = int(match.group(1))
105 except ValueError:
106 raise ParseError("Invalid value [%s] for parameter number" % match.group(1))
107 value_match = value_re.match(self.bridge_template.get(name, option))
108 if not value_match:
109 raise ParseError("Invalid value for parameter doc [%i]" % idx)
110 doc_dict[idx]=(value_match.group(1),value_match.group(2))
111 return doc_dict
112
113 def getArguments(self, signature, name=None, default=None):
72 """Return arguments to user given a signature 114 """Return arguments to user given a signature
73 @param signature: signature in the short form (using s,a,i,b etc) 115 @param signature: signature in the short form (using s,a,i,b etc)
74 @return: list of arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")""" 116 @return: list of arguments that correspond to a signature (e.g.: "sss" return "arg1, arg2, arg3")"""
75 i=0 117 i=0
76 idx=0 118 idx=0
77 attr_string="" 119 attr_string=""
78 while i<len(signature): 120 while i<len(signature):
79 if signature[i] not in ['b','y','n','i','x','q','u','t','d','s','a']: 121 if signature[i] not in ['b','y','n','i','x','q','u','t','d','s','a']:
80 raise ParseError("Unmanaged attribute type [%c]" % signature[i]) 122 raise ParseError("Unmanaged attribute type [%c]" % signature[i])
81 123
82 attr_string += ("" if idx==0 else ", ") + ("arg_%i" % idx) 124 attr_string += ("" if idx==0 else ", ") + ("%(name)s%(default)s" % {
125 'name':name[idx][0] if (name and name.has_key(idx)) else "arg_%i" % idx,
126 'default':"="+default[idx] if (default and default.has_key(idx)) else ''
127 }) #give arg_1, arg2, etc or name1, name2=default, etc
83 idx+=1 128 idx+=1
84 129
85 if signature[i] == 'a': 130 if signature[i] == 'a':
86 i+=1 131 i+=1
87 if signature[i]!='{' and signature[i]!='(': #FIXME: must manage tuples out of arrays 132 if signature[i]!='{' and signature[i]!='(': #FIXME: must manage tuples out of arrays
88 i+=1 133 i+=1
89 continue #we have a simple type for the array 134 continue #we have a simple type for the array
90 opening_car = signature[i] 135 opening_car = signature[i]
136 assert(opening_car in ['{','('])
91 closing_car = '}' if opening_car == '{' else ')' 137 closing_car = '}' if opening_car == '{' else ')'
92 opening_count = 1 138 opening_count = 1
93 while (True): #we have a dict or a list of tuples 139 while (True): #we have a dict or a list of tuples
94 i+=1 140 i+=1
95 if i>=len(signature): 141 if i>=len(signature):
121 sections = self.bridge_template.sections() 167 sections = self.bridge_template.sections()
122 sections.sort() 168 sections.sort()
123 for section in sections: 169 for section in sections:
124 function = self.getValues(section) 170 function = self.getValues(section)
125 print ("Adding %s %s" % (section, function["type"])) 171 print ("Adding %s %s" % (section, function["type"]))
172 default = self.getDefault(section)
173 arg_doc = self.getArgumentsDoc(section)
126 completion = { 174 completion = {
127 'sig_in':function['sig_in'] or '', 175 'sig_in':function['sig_in'] or '',
128 'sig_out':function['sig_out'] or '', 176 'sig_out':function['sig_out'] or '',
129 'category':'REQ' if function['category'] == 'request' else 'COMM', 177 'category':'REQ' if function['category'] == 'request' else 'COMM',
130 'name':section, 178 'name':section,
131 'args':self.getArguments(function['sig_in']) 179 'args':self.getArguments(function['sig_in'], name=arg_doc, default=default, )
132 } 180 }
133 181
134 if function["type"] == "signal": 182 if function["type"] == "signal":
135 completion['body'] = "pass" if not self.options.debug else 'debug ("%s")' % section 183 completion['body'] = "pass" if not self.options.debug else 'debug ("%s")' % section
136 signals_part.append("""\ 184 signals_part.append("""\
144 self.dbus_bridge.%(name)s(%(args)s) 192 self.dbus_bridge.%(name)s(%(args)s)
145 """ % completion) 193 """ % completion)
146 194
147 elif function["type"] == "method": 195 elif function["type"] == "method":
148 completion['debug'] = "" if not self.options.debug else 'debug ("%s")\n%s' % (section,8*' ') 196 completion['debug'] = "" if not self.options.debug else 'debug ("%s")\n%s' % (section,8*' ')
197 completion['args_nodefault'] = self.getArguments(function['sig_in'], name=arg_doc)
149 methods_part.append("""\ 198 methods_part.append("""\
150 @dbus.service.method(const_INT_PREFIX+const_%(category)s_SUFFIX, 199 @dbus.service.method(const_INT_PREFIX+const_%(category)s_SUFFIX,
151 in_signature='%(sig_in)s', out_signature='%(sig_out)s') 200 in_signature='%(sig_in)s', out_signature='%(sig_out)s')
152 def %(name)s(self, %(args)s): 201 def %(name)s(self, %(args)s):
153 %(debug)sreturn self.cb["%(name)s"](%(args)s) 202 %(debug)sreturn self.cb["%(name)s"](%(args_nodefault)s)
154 """ % completion) 203 """ % completion)
155 204
156 #at this point, signals_part, methods_part and direct_calls should be filled, 205 #at this point, signals_part, methods_part and direct_calls should be filled,
157 #we just have to place them in the right part of the template 206 #we just have to place them in the right part of the template
158 core_bridge = [] 207 core_bridge = []