cloudstack/tools/testClient/codegenerator.py
2012-04-03 04:50:05 -07:00

290 lines
11 KiB
Python

# Copyright 2012 Citrix Systems, Inc. Licensed under the
# Apache License, Version 2.0 (the "License"); you may not use this
# file except in compliance with the License. Citrix Systems, Inc.
# reserves all rights not expressly granted by the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Automatically generated by addcopyright.py at 04/03/2012
import xml.dom.minidom
from optparse import OptionParser
import os
import sys
class cmdParameterProperty(object):
def __init__(self):
self.name = None
self.required = False
self.desc = ""
self.type = "planObject"
self.subProperties = []
class cloudStackCmd:
def __init__(self):
self.name = ""
self.desc = ""
self.async = "false"
self.request = []
self.response = []
class codeGenerator:
space = " "
cmdsName = []
def __init__(self, outputFolder, apiSpecFile):
self.cmd = None
self.code = ""
self.required = []
self.subclass = []
self.outputFolder = outputFolder
self.apiSpecFile = apiSpecFile
def addAttribute(self, attr, pro):
value = pro.value
if pro.required:
self.required.append(attr)
desc = pro.desc
if desc is not None:
self.code += self.space
self.code += "''' " + pro.desc + " '''"
self.code += "\n"
self.code += self.space
self.code += attr + " = " + str(value)
self.code += "\n"
def generateSubClass(self, name, properties):
'''generate code for sub list'''
subclass = 'class %s:\n'%name
subclass += self.space + "def __init__(self):\n"
for pro in properties:
if pro.desc is not None:
subclass += self.space + self.space + '""""%s"""\n'%pro.desc
if len (pro.subProperties) > 0:
subclass += self.space + self.space + 'self.%s = []\n'%pro.name
self.generateSubClass(pro.name, pro.subProperties)
else:
subclass += self.space + self.space + 'self.%s = None\n'%pro.name
self.subclass.append(subclass)
def generate(self, cmd):
self.cmd = cmd
self.cmdsName.append(self.cmd.name)
self.code += "\n"
self.code += '"""%s"""\n'%self.cmd.desc
self.code += 'from baseCmd import *\n'
self.code += 'from baseResponse import *\n'
self.code += "class %sCmd (baseCmd):\n"%self.cmd.name
self.code += self.space + "def __init__(self):\n"
self.code += self.space + self.space + 'self.isAsync = "%s"\n' %self.cmd.async
for req in self.cmd.request:
if req.desc is not None:
self.code += self.space + self.space + '"""%s"""\n'%req.desc
if req.required == "true":
self.code += self.space + self.space + '"""Required"""\n'
value = "None"
if req.type == "list" or req.type == "map":
value = "[]"
self.code += self.space + self.space + 'self.%s = %s\n'%(req.name,value)
if req.required == "true":
self.required.append(req.name)
self.code += self.space + self.space + "self.required = ["
for require in self.required:
self.code += '"' + require + '",'
self.code += "]\n"
self.required = []
"""generate response code"""
subItems = {}
self.code += "\n"
self.code += 'class %sResponse (baseResponse):\n'%self.cmd.name
self.code += self.space + "def __init__(self):\n"
if len(self.cmd.response) == 0:
self.code += self.space + self.space + "pass"
else:
for res in self.cmd.response:
if res.desc is not None:
self.code += self.space + self.space + '"""%s"""\n'%res.desc
if len(res.subProperties) > 0:
self.code += self.space + self.space + 'self.%s = []\n'%res.name
self.generateSubClass(res.name, res.subProperties)
else:
self.code += self.space + self.space + 'self.%s = None\n'%res.name
self.code += '\n'
for subclass in self.subclass:
self.code += subclass + "\n"
fp = open(self.outputFolder + "/cloudstackAPI/%s.py"%self.cmd.name, "w")
fp.write(self.code)
fp.close()
self.code = ""
self.subclass = []
def finalize(self):
'''generate an api call'''
header = '"""Test Client for CloudStack API"""\n'
imports = "import copy\n"
initCmdsList = '__all__ = ['
body = ''
body += "class CloudStackAPIClient:\n"
body += self.space + 'def __init__(self, connection):\n'
body += self.space + self.space + 'self.connection = connection\n'
body += "\n"
body += self.space + 'def __copy__(self):\n'
body += self.space + self.space + 'return CloudStackAPIClient(copy.copy(self.connection))\n'
body += "\n"
for cmdName in self.cmdsName:
body += self.space + 'def %s(self,command):\n'%cmdName
body += self.space + self.space + 'response = %sResponse()\n'%cmdName
body += self.space + self.space + 'response = self.connection.make_request(command, response)\n'
body += self.space + self.space + 'return response\n'
body += '\n'
imports += 'from %s import %sResponse\n'%(cmdName, cmdName)
initCmdsList += '"%s",'%cmdName
fp = open(self.outputFolder + '/cloudstackAPI/cloudstackAPIClient.py', 'w')
for item in [header, imports, body]:
fp.write(item)
fp.close()
'''generate __init__.py'''
initCmdsList += '"cloudstackAPIClient"]'
fp = open(self.outputFolder + '/cloudstackAPI/__init__.py', 'w')
fp.write(initCmdsList)
fp.close()
fp = open(self.outputFolder + '/cloudstackAPI/baseCmd.py', 'w')
basecmd = '"""Base Command"""\n'
basecmd += 'class baseCmd:\n'
basecmd += self.space + 'pass\n'
fp.write(basecmd)
fp.close()
fp = open(self.outputFolder + '/cloudstackAPI/baseResponse.py', 'w')
basecmd = '"""Base class for response"""\n'
basecmd += 'class baseResponse:\n'
basecmd += self.space + 'pass\n'
fp.write(basecmd)
fp.close()
def constructResponse(self, response):
paramProperty = cmdParameterProperty()
paramProperty.name = getText(response.getElementsByTagName('name'))
paramProperty.desc = getText(response.getElementsByTagName('description'))
if paramProperty.name.find('(*)') != -1:
'''This is a list'''
paramProperty.name = paramProperty.name.split('(*)')[0]
for subresponse in response.getElementsByTagName('arguments')[0].getElementsByTagName('arg'):
subProperty = self.constructResponse(subresponse)
paramProperty.subProperties.append(subProperty)
return paramProperty
def loadCmdFromXML(self):
dom = xml.dom.minidom.parse(self.apiSpecFile)
cmds = []
for cmd in dom.getElementsByTagName("command"):
csCmd = cloudStackCmd()
csCmd.name = getText(cmd.getElementsByTagName('name'))
assert csCmd.name
desc = getText(cmd.getElementsByTagName('description'))
if desc:
csCmd.desc = desc
async = getText(cmd.getElementsByTagName('isAsync'))
if async:
csCmd.async = async
for param in cmd.getElementsByTagName("request")[0].getElementsByTagName("arg"):
paramProperty = cmdParameterProperty()
paramProperty.name = getText(param.getElementsByTagName('name'))
assert paramProperty.name
required = param.getElementsByTagName('required')
if required:
paramProperty.required = getText(required)
requestDescription = param.getElementsByTagName('description')
if requestDescription:
paramProperty.desc = getText(requestDescription)
type = param.getElementsByTagName("type")
if type:
paramProperty.type = getText(type)
csCmd.request.append(paramProperty)
responseEle = cmd.getElementsByTagName("response")[0]
for response in responseEle.getElementsByTagName("arg"):
if response.parentNode != responseEle:
continue
paramProperty = self.constructResponse(response)
csCmd.response.append(paramProperty)
cmds.append(csCmd)
return cmds
def generateCode(self):
cmds = self.loadCmdFromXML()
for cmd in cmds:
self.generate(cmd)
self.finalize()
def getText(elements):
return elements[0].childNodes[0].nodeValue.strip()
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-o", "--output", dest="output", help="the root path where code genereted, default is .")
parser.add_option("-s", "--specfile", dest="spec", help="the path and name of the api spec xml file, default is /etc/cloud/cli/commands.xml")
(options, args) = parser.parse_args()
apiSpecFile = "/etc/cloud/cli/commands.xml"
if options.spec is not None:
apiSpecFile = options.spec
if not os.path.exists(apiSpecFile):
print "the spec file %s does not exists"%apiSpecFile
print parser.print_help()
exit(1)
folder = "."
if options.output is not None:
folder = options.output
apiModule=folder + "/cloudstackAPI"
if not os.path.exists(apiModule):
try:
os.mkdir(apiModule)
except:
print "Failed to create folder %s, due to %s"%(apiModule,sys.exc_info())
print parser.print_help()
exit(2)
cg = codeGenerator(folder, apiSpecFile)
cg.generateCode()