linphone-ios/tools/python/apixml2python/linphone.py

167 lines
5.8 KiB
Python

class LinphoneModule(object):
def __init__(self, tree):
self.enums = []
xml_enums = tree.findall("./enums/enum")
for xml_enum in xml_enums:
e = {}
e['enum_name'] = xml_enum.get('name')
e['enum_doc'] = self.__format_doc(xml_enum.find('briefdescription'), xml_enum.find('detaileddescription'))
e['enum_values'] = []
xml_enum_values = xml_enum.findall("./values/value")
for xml_enum_value in xml_enum_values:
v = {}
v['enum_value_name'] = xml_enum_value.get('name')
e['enum_values'].append(v)
self.enums.append(e)
self.classes = []
xml_classes = tree.findall("./classes/class")
for xml_class in xml_classes:
c = {}
c['class_name'] = xml_class.get('name')
c['class_c_function_prefix'] = xml_class.get('cfunctionprefix')
c['class_doc'] = self.__format_doc(xml_class.find('briefdescription'), xml_class.find('detaileddescription'))
c['class_type_methods'] = []
xml_type_methods = xml_class.findall("./classmethods/classmethod")
for xml_type_method in xml_type_methods:
m = {}
m['method_name'] = xml_type_method.get('name').replace(c['class_c_function_prefix'], '')
m['method_body'] = self.__format_method_body(xml_type_method, c['class_name'])
c['class_type_methods'].append(m)
c['class_instance_methods'] = []
xml_instance_methods = xml_class.findall("./instancemethods/instancemethod")
for xml_instance_method in xml_instance_methods:
m = {}
m['method_name'] = xml_instance_method.get('name').replace(c['class_c_function_prefix'], '')
c['class_instance_methods'].append(m)
c['class_properties'] = []
xml_properties = xml_class.findall("./properties/property")
for xml_property in xml_properties:
p = {}
p['property_name'] = xml_property.get('name')
xml_property_getter = xml_property.find("./getter")
xml_property_setter = xml_property.find("./setter")
if xml_property_getter is not None:
p['getter_name'] = xml_property_getter.get('name').replace(c['class_c_function_prefix'], '')
if xml_property_setter is not None:
p['setter_name'] = xml_property_setter.get('name').replace(c['class_c_function_prefix'], '')
c['class_properties'].append(p)
self.classes.append(c)
def __ctype_to_python_format(self, ctype):
keywords = ['const', 'struct', 'enum', 'signed', 'unsigned', 'short', 'long', '*']
splitted_type = ctype.split(' ')
for s in splitted_type:
if s not in keywords:
basic_type = s
break
if basic_type == 'char':
if '*' in splitted_type:
return 's'
elif 'unsigned' in splitted_type:
return 'b'
elif basic_type == 'int':
# TODO:
return 'i'
elif basic_type == 'int8_t':
return 'c'
elif basic_type == 'uint8_t':
return 'b'
elif basic_type == 'int16_t':
return 'h'
elif basic_type == 'uint16_t':
return 'H'
elif basic_type == 'int32_t':
return 'l'
elif basic_type == 'uint32_t':
return 'k'
elif basic_type == 'int64_t':
return 'L'
elif basic_type == 'uint64_t':
return 'K'
elif basic_type == 'size_t':
return 'n'
elif basic_type == 'float':
return 'f'
elif basic_type == 'double':
return 'd'
else:
return 'O'
def __format_method_body(self, method_node, class_name):
body = ''
parse_tuple_format = ''
xml_method_return = method_node.find('./return')
return_type = xml_method_return.get('type')
if return_type != 'void':
body += "\t" + return_type + " cresult;\n"
build_value_format = self.__ctype_to_python_format(return_type)
if build_value_format == 'O':
body += "\tPyObject * pyresult;\n"
body += "\tPyObject * pyret;\n"
xml_method_args = method_node.findall('./arguments/argument')
arg_names = []
for xml_method_arg in xml_method_args:
parse_tuple_format += self.__ctype_to_python_format(xml_method_arg.get('type'))
body += "\t" + xml_method_arg.get('type') + " " + xml_method_arg.get('name') + ";\n"
arg_names.append(xml_method_arg.get('name'))
if len(xml_method_args) > 0:
body += "\n\tif (!PyArg_ParseTuple(args, \"" + parse_tuple_format + "\""
body += ', ' + ', '.join(map(lambda a: '&' + a, arg_names))
body += ")) {\n\t\treturn NULL;\n\t}\n\n"
body += "\tpylinphone_trace(__FUNCTION__);\n\n"
body += "\t"
if return_type != 'void':
body += "cresult = "
body += method_node.get('name') + "(" + ', '.join(arg_names) + ");\n"
if return_type != 'void':
if build_value_format == 'O':
body += "\tpyresult = pylinphone_" + class_name + "_new_from_native_ptr(&pylinphone_" + class_name + "Type, cresult);\n"
body += "\tpyret = Py_BuildValue(\"" + build_value_format + "\", pyresult);\n"
body += "\tPy_DECREF(pyresult);\n"
body += "\treturn pyret;"
else:
body += "\treturn Py_BuildValue(\"" + build_value_format + "\", cresult);"
else:
body += "\tPy_RETURN_NONE;"
return body
def __format_doc_node(self, node):
desc = ''
if node.tag == 'para':
desc += node.text.strip()
for n in list(node):
desc += self.__format_doc_node(n)
elif node.tag == 'note':
desc += node.text.strip()
for n in list(node):
desc += self.__format_doc_node(n)
elif node.tag == 'ref':
desc += ' ' + node.text.strip() + ' '
tail = node.tail.strip()
if tail != '':
if node.tag != 'ref':
desc += '\n'
desc += tail
if node.tag == 'para':
desc += '\n'
return desc
def __format_doc(self, brief_description, detailed_description):
doc = ''
if brief_description is None:
brief_description = ''
if detailed_description is None:
detailed_description = ''
else:
desc = ''
for node in list(detailed_description):
desc += self.__format_doc_node(node) + '\n'
detailed_description = desc.strip().replace('\n', '\\n')
brief_description = brief_description.strip()
doc += brief_description
if detailed_description != '':
if doc != '':
doc += '\\n\\n'
doc+= detailed_description
doc = '\"' + doc + '\"'
return doc