medit/api/mdp/xmlwriter.py

155 lines
5.6 KiB
Python

import xml.etree.ElementTree as etree
import mdp.module as module
class Writer(object):
def __init__(self, out):
object.__init__(self)
self.out = out
self.xml = etree.TreeBuilder()
self.__tag_opened = False
self.__depth = 0
def __start_tag(self, tag, attrs={}):
if self.__tag_opened:
self.xml.data('\n')
if self.__depth > 0:
self.xml.data(' ' * self.__depth)
elm = self.xml.start(tag, attrs)
self.__tag_opened = True
self.__depth += 1
return elm
def __end_tag(self, tag):
if not self.__tag_opened and self.__depth > 1:
self.xml.data(' ' * (self.__depth - 1))
elm = self.xml.end(tag)
self.xml.data('\n')
self.__tag_opened = False
self.__depth -= 1
return elm
def __write_docs(self, docs):
if not docs:
return
self.__start_tag('doc')
docs = ' '.join(docs)
self.xml.data(docs)
self.__end_tag('doc')
def __write_param_or_retval_annotations(self, param, elm):
for k in param.attributes:
elm.set(k, self.attributes[v])
if param.transfer_mode is not None:
elm.set('transfer_mode', param.transfer_mode)
if param.element_type is not None:
elm.set('element_type', param.element_type)
if param.array:
elm.set('array', '1')
if param.array_fixed_len is not None:
elm.set('array_fixed_len', str(param.array_fixed_len))
if param.array_len_param is not None:
elm.set('array_len_param', param.array_len_param)
if param.array_zero_terminated:
elm.set('array_zero_terminated', '1')
def __write_param_annotations(self, param, elm):
self.__write_param_or_retval_annotations(param, elm)
if param.inout:
elm.set('inout', '1')
elif param.out:
elm.set('out', '1')
if param.caller_allocates:
elm.set('caller_allocates', '1')
elif param.callee_allocates:
elm.set('callee_allocates', '1')
if param.allow_none:
elm.set('allow_none', '1')
if param.default_value is not None:
elm.set('default_value', param.default_value)
if param.scope != 'call':
elm.set('scope', param.scope)
def __write_retval_annotations(self, retval, elm):
self.__write_param_or_retval_annotations(retval, elm)
def __write_param(self, param):
dic = dict(name=param.name, type=param.type)
elm = self.__start_tag('param', dic)
self.__write_param_annotations(param, elm)
self.__write_docs(param.docs)
self.__end_tag('param')
def __write_retval(self, retval):
dic = dict(type=retval.type)
elm = self.__start_tag('retval', dic)
self.__write_retval_annotations(retval, elm)
self.__write_docs(retval.docs)
self.__end_tag('retval')
def __write_class(self, cls):
if not cls.parent:
raise RuntimeError('parent missing in class %s' % (cls.name,))
dic = dict(name=cls.name, short_name=cls.short_name, parent=cls.parent, gtype_id=cls.gtype_id)
if cls.constructable:
dic['constructable'] = '1'
self.__start_tag('class', dic)
if cls.constructor is not None:
self.__write_function(cls.constructor, 'constructor')
for meth in sorted(cls.vmethods, lambda x, y: cmp(x.name, y.name)):
self.__write_function(meth, 'virtual')
for meth in sorted(cls.methods, lambda x, y: cmp(x.name, y.name)):
self.__write_function(meth, 'method')
self.__write_docs(cls.docs)
self.__end_tag('class')
def __write_boxed(self, cls):
dic = dict(name=cls.name, short_name=cls.short_name, gtype_id=cls.gtype_id)
tag = 'boxed' if isinstance(cls, module.Boxed) else 'pointer'
self.__start_tag(tag, dic)
if cls.constructor is not None:
self.__write_function(cls.constructor, 'constructor')
for meth in cls.methods:
self.__write_function(meth, 'method')
self.__write_docs(cls.docs)
self.__end_tag(tag)
def __write_enum(self, enum):
if isinstance(enum, module.Enum):
tag = 'enum'
else:
tag = 'flags'
dic = dict(name=enum.name, short_name=enum.short_name, gtype_id=enum.gtype_id)
self.__start_tag(tag, dic)
self.__write_docs(enum.docs)
self.__end_tag(tag)
def __write_function(self, func, tag):
dic = dict(name=func.name)
if tag != 'virtual':
dic['c_name'] = func.c_name
self.__start_tag(tag, dic)
for p in func.params:
self.__write_param(p)
if func.retval:
self.__write_retval(func.retval)
self.__write_docs(func.docs)
self.__end_tag(tag)
def write(self, module):
self.__start_tag('module', dict(name=module.name))
for cls in sorted(module.classes, lambda x, y: cmp(x.name, y.name)):
self.__write_class(cls)
for cls in sorted(module.boxed, lambda x, y: cmp(x.name, y.name)):
self.__write_boxed(cls)
for enum in sorted(module.enums, lambda x, y: cmp(x.name, y.name)):
self.__write_enum(enum)
for func in sorted(module.functions, lambda x, y: cmp(x.name, y.name)):
self.__write_function(func, 'function')
self.__end_tag('module')
elm = self.xml.close()
etree.ElementTree(elm).write(self.out)
def write_xml(module, out):
Writer(out).write(module)