File indexing completed on 2024-05-12 16:08:36

0001 #!/usr/bin/env python2.7
0002 # This file is part of KDevelop
0003 # SPDX-FileCopyrightText: 2011 Victor Varvariuc <victor.varvariuc@gmail.com>
0004 
0005 from xml.dom import minidom
0006 
0007 
0008 def indentCode(code, level):
0009     return '\n'.join('    ' * level + line for line in code.splitlines())
0010 
0011 
0012 def parseEnum(enumNode, enumName, className = ''):
0013     '''Parse Enum node and return its string representation.'''
0014     enumMembers = []
0015     for node in enumNode.childNodes:
0016         if node.nodeType == node.ELEMENT_NODE:
0017             if node.nodeName == 'EnumMember':
0018                 enumMember = node.attributes['name'].value
0019                 if enumMember.startswith(className + '.'):
0020                     enumMember = enumMember[len(className) + 1:]
0021                 if enumMember == 'None':
0022                     enumMember = '__kdevpythondocumentation_builtin_None'
0023                 enumMembers.append(enumMember)
0024             else:
0025                 print 'Unknown node in Enum %s.%s: %s' % (className, enumName, node.nodeName)
0026     text = ''
0027     for enumMember in enumMembers:
0028         text += '%s = int() # %s.%s enum\n' % (enumMember, className, enumName)
0029     return text
0030 
0031 
0032 def parseFunction(functionNode, funcName, className = ''):
0033     '''Parse Function node and return its string representation.'''
0034     params = [] if className == '' else [("None", "self")]
0035     retType = 'None'
0036     namesUsed = []
0037     for node in functionNode.childNodes:
0038         if node.nodeType == node.ELEMENT_NODE:
0039             if node.nodeName == 'Argument':
0040                 argType = node.attributes['typename'].value
0041                 try:
0042                     argName = '*args' if argType == '...' else '_' + node.attributes['name'].value
0043                 except KeyError:
0044                     retType = argType
0045                 else:
0046                     if argName not in namesUsed:
0047                         params.append((argType, argName))
0048                     else:
0049                         print "adjusting arg name:", argName
0050                         argName = argName + '_'
0051                         params.append((argType, argName))
0052                     namesUsed.append(argName)
0053             else:
0054                 print 'Unknown node in function %s.%s: %s' % (className, funcName, node.nodeName)
0055 
0056     descr = 'abstract ' if 'abstract' in functionNode.attributes.keys() else ''
0057     descr += '%s %s.%s(%s)' % (retType, className, funcName,
0058                 ', '.join('%s %s' % p for p in params))
0059 
0060     if retType == 'None':
0061         pass # leave it like this
0062     elif retType.startswith('list-of-'):
0063         retType = '[' + retType[8:] + '()]'
0064     else:
0065         retType += '()'
0066 
0067     # prefix function arguments with '_' to deal with reserved Python keywords
0068     text = 'def %s(%s):\n    """%s"""\n    return %s' % (funcName, ', '.join(param[1] for param in params), descr, retType)
0069     return text
0070 
0071 
0072 def parseClass(classNode):
0073     '''Parse Class node.'''
0074     try:
0075         parentClasses = classNode.attributes['inherits'].value.split()
0076     except KeyError:
0077         parentClasses = []
0078     className = classNode.attributes['name'].value
0079     text = 'class %s(%s):\n    """"""\n' % (className, ', '.join(parentClasses))
0080     for node in classNode.childNodes:
0081         if node.nodeType == node.ELEMENT_NODE:
0082             name = node.attributes['name'].value
0083             if name.startswith(className + '.'):
0084                 name = name[len(className) + 1 :]
0085             if node.nodeName == 'Member':
0086                 text += '    %s = None # %s member\n' % (name, node.attributes['typename'].value)
0087             elif node.nodeName == 'Function':
0088                 if name not in ('exec', 'print'): # skip this invalid for Python name
0089                     text += indentCode(parseFunction(node, name, className), 1) + '\n'
0090             elif node.nodeName == 'Enum':
0091                 text += indentCode(parseEnum(node, name, className), 1) + '\n\n'
0092             else:
0093                 print 'Unknown node in class %s: %s' % (className, node.nodeName)
0094     return text
0095 
0096 
0097 files = ['QtGuimod.xml', 'QtCoremod.xml']
0098 for filename in files:
0099     dom = minidom.parse(filename)
0100 
0101     module = dom.firstChild
0102     assert module.nodeName == 'Module'
0103     moduleName = module.attributes['name'].value
0104     print 'Module name:', moduleName
0105 
0106     stats = {}
0107 
0108     with open(moduleName + '.py', 'w') as file:
0109         for node in module.childNodes:
0110             if node.nodeType != node.ELEMENT_NODE:
0111                 continue # skip non element nodes
0112             nodeName = node.nodeName
0113             stats[nodeName] = stats.setdefault(nodeName, 0) + 1 # stats
0114             if nodeName == 'Class':
0115                 file.write(parseClass(node) + '\n\n')
0116             elif nodeName == 'Function':
0117                 file.write(parseFunction(node, node.attributes['name'].value) + '\n\n')
0118             elif nodeName == 'Member':
0119                 file.write('%s = None # %s member\n\n' % (node.attributes['name'].value, node.attributes['typename'].value))
0120             else:
0121                 print 'Unknown node:', nodeName
0122 
0123     print 'Stats:', stats