mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-02-07 14:18:25 +00:00
Begin generation of python module code.
This commit is contained in:
parent
2472742b6f
commit
76c467a163
5 changed files with 288 additions and 0 deletions
30
tools/python/apixml2python.py
Executable file
30
tools/python/apixml2python.py
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pystache
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
sys.path.append(os.path.realpath(__file__))
|
||||
from apixml2python.linphone import LinphoneModule
|
||||
|
||||
|
||||
def generate(apixmlfile):
|
||||
tree = ET.parse(apixmlfile)
|
||||
renderer = pystache.Renderer()
|
||||
m = LinphoneModule(tree)
|
||||
f = open("linphone.c", "w")
|
||||
f.write(renderer.render(m))
|
||||
|
||||
|
||||
def main(argv = None):
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
argparser = argparse.ArgumentParser(description="Generate a Python wrapper of the Linphone API.")
|
||||
argparser.add_argument('apixmlfile', help="XML file of the Linphone API generated by genapixml.py.")
|
||||
args = argparser.parse_args()
|
||||
generate(args.apixmlfile)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
0
tools/python/apixml2python/__init__.py
Normal file
0
tools/python/apixml2python/__init__.py
Normal file
88
tools/python/apixml2python/linphone.py
Normal file
88
tools/python/apixml2python/linphone.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
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'], '')
|
||||
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 __format_node(self, node):
|
||||
desc = ''
|
||||
if node.tag == 'para':
|
||||
desc += node.text.strip()
|
||||
for n in list(node):
|
||||
desc += self.__format_node(n)
|
||||
elif node.tag == 'note':
|
||||
desc += node.text.strip()
|
||||
for n in list(node):
|
||||
desc += self.__format_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_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
|
||||
161
tools/python/apixml2python/linphone_module.mustache
Normal file
161
tools/python/apixml2python/linphone_module.mustache
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
#include <Python.h>
|
||||
#include <linphone/linphonecore.h>
|
||||
|
||||
{{#classes}}
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
{{class_name}} *native_ptr;
|
||||
} pylinphone_{{class_name}}Object;
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
|
||||
pylinphone_{{class_name}}Object *self = (pylinphone_{{class_name}}Object *)type->tp_alloc(type, 0);
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
static void pylinphone_{{class_name}}_dealloc(PyObject *self) {
|
||||
self->ob_type->tp_free(self);
|
||||
}
|
||||
|
||||
{{#class_type_methods}}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_type_method_{{method_name}}(PyObject *self, PyObject *args) {
|
||||
// TODO: Fill implementation
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
{{/class_type_methods}}
|
||||
|
||||
static PyMethodDef pylinphone_{{class_name}}_type_methods[] = {
|
||||
// TODO: Handle doc
|
||||
{{#class_type_methods}}
|
||||
{ "{{method_name}}", pylinphone_{{class_name}}_type_method_{{method_name}}, METH_VARARGS, "" },
|
||||
{{/class_type_methods}}
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
{{#class_instance_methods}}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyObject *self, PyObject *args) {
|
||||
// TODO: Fill implementation
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
{{/class_instance_methods}}
|
||||
|
||||
static PyMethodDef pylinphone_{{class_name}}_instance_methods[] = {
|
||||
// TODO: Handle doc
|
||||
{{#class_instance_methods}}
|
||||
{ "{{method_name}}", pylinphone_{{class_name}}_instance_method_{{method_name}}, METH_VARARGS, "" },
|
||||
{{/class_instance_methods}}
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
{{#class_properties}}
|
||||
|
||||
static PyObject * pylinphone_{{class_name}}_{{getter_name}}(pylinphone_{{class_name}}Object *self, void *closure) {
|
||||
// TODO: Fill implementation
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static int pylinphone_{{class_name}}_{{setter_name}}(pylinphone_{{class_name}}Object *self, PyObject *value, void *closure) {
|
||||
// TODO: Fill implementation
|
||||
return 0;
|
||||
}
|
||||
|
||||
{{/class_properties}}
|
||||
|
||||
static PyGetSetDef pylinphone_{{class_name}}_getseters[] = {
|
||||
// TODO: Handle doc
|
||||
{{#class_properties}}
|
||||
{ "{{property_name}}", (getter)pylinphone_{{class_name}}_{{getter_name}}, (setter)pylinphone_{{class_name}}_{{setter_name}}, "" },
|
||||
{{/class_properties}}
|
||||
{ NULL, NULL, NULL, NULL, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject pylinphone_{{class_name}}Type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"linphone.{{name}}", /* tp_name */
|
||||
sizeof(pylinphone_{{class_name}}Object), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
pylinphone_{{class_name}}_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
{{{class_doc}}}, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
pylinphone_{{class_name}}_instance_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
pylinphone_{{class_name}}_getseters, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
pylinphone_{{class_name}}_new, /* tp_new */
|
||||
0, /* tp_free */
|
||||
};
|
||||
|
||||
{{/classes}}
|
||||
|
||||
static PyMethodDef pylinphone_ModuleMethods[] = {
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
static PyMethodDef pylinphone_NoMethods[] = {
|
||||
{ NULL, NULL, 0, NULL } /* Sentinel */
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC initlinphone(void) {
|
||||
PyObject *m;
|
||||
PyObject *menum;
|
||||
PyMethodDef *def;
|
||||
|
||||
{{#classes}}
|
||||
if (PyType_Ready(&pylinphone_{{class_name}}Type) < 0) return;
|
||||
{{/classes}}
|
||||
|
||||
m = Py_InitModule3("linphone", pylinphone_ModuleMethods, "Python module giving access to the Linphone library.");
|
||||
if (m == NULL) return;
|
||||
|
||||
{{#enums}}
|
||||
menum = Py_InitModule3("{{enum_name}}", pylinphone_NoMethods, {{{enum_doc}}});
|
||||
if (menum == NULL) return;
|
||||
if (PyModule_AddObject(m, "{{enum_name}}", menum) < 0) return;
|
||||
{{#enum_values}}
|
||||
if (PyModule_AddIntConstant(menum, "{{enum_value_name}}", {{enum_value_name}}) < 0) return;
|
||||
{{/enum_values}}
|
||||
{{/enums}}
|
||||
|
||||
{{#classes}}
|
||||
Py_INCREF(&pylinphone_{{class_name}}Type);
|
||||
PyModule_AddObject(m, "{{class_name}}", (PyObject *)&pylinphone_{{class_name}}Type);
|
||||
for (def = pylinphone_{{class_name}}_type_methods; def->ml_name != NULL; def++) {
|
||||
PyObject *func = PyCFunction_New(def, NULL);
|
||||
PyObject *method = PyMethod_New(func, NULL, (PyObject *)&pylinphone_{{class_name}}Type);
|
||||
PyDict_SetItemString(pylinphone_{{class_name}}Type.tp_dict, def->ml_name, method);
|
||||
Py_DECREF(method);
|
||||
Py_DECREF(func);
|
||||
}
|
||||
{{/classes}}
|
||||
}
|
||||
9
tools/python/setup.py
Normal file
9
tools/python/setup.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
m = Extension('linphone',
|
||||
include_dirs = ['/home/ghislain/linphone-install/include'],
|
||||
sources = ['linphone.c']
|
||||
)
|
||||
setup(name = 'Linphone', version = '1.0', description = 'Linphone package', ext_modules = [m])
|
||||
Loading…
Add table
Reference in a new issue