From 1c50f1c75665524857f7410f1b3525717dcfcd03 Mon Sep 17 00:00:00 2001 From: Daan Hoogland Date: Fri, 21 Jun 2013 15:18:48 +0200 Subject: [PATCH] CLOUDSTACK-3096: format codegenerator.py --- tools/marvin/marvin/codegenerator.py | 143 ++++++++++++++++----------- 1 file changed, 86 insertions(+), 57 deletions(-) diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py index 36ba1800081..1f25e5379be 100644 --- a/tools/marvin/marvin/codegenerator.py +++ b/tools/marvin/marvin/codegenerator.py @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with 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 @@ -23,6 +23,7 @@ import os import sys import urllib2 + class cmdParameterProperty(object): def __init__(self): self.name = None @@ -30,7 +31,8 @@ class cmdParameterProperty(object): self.desc = "" self.type = "planObject" self.subProperties = [] - + + class cloudStackCmd: def __init__(self): self.name = "" @@ -42,8 +44,9 @@ class cloudStackCmd: class codeGenerator: """ - Apache CloudStack- marvin python classes can be generated from the json returned by API discovery or from the - xml spec of commands generated by the ApiDocWriter. This class provides helper methods for these uses. + Apache CloudStack- marvin python classes can be generated from the json + returned by API discovery or from the xml spec of commands generated by + the ApiDocWriter. This class provides helper methods for these uses. """ space = " " cmdsName = [] @@ -91,16 +94,18 @@ class codeGenerator: def generateSubClass(self, name, properties): '''generate code for sub list''' - subclass = 'class %s:\n'%name + 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 + subclass += self.space + self.space + '""""%s"""\n' % pro.desc + if len(pro.subProperties) > 0: + subclass += self.space + self.space + subclass += 'self.%s = []\n' % pro.name self.generateSubClass(pro.name, pro.subProperties) else: - subclass += self.space + self.space + 'self.%s = None\n'%pro.name + subclass += self.space + self.space + subclass += 'self.%s = None\n' % pro.name self.subclass.append(subclass) @@ -110,17 +115,18 @@ class codeGenerator: self.cmdsName.append(self.cmd.name) self.code = self.license self.code += "\n" - self.code += '"""%s"""\n'%self.cmd.desc + 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 += "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' %str(self.cmd.async).lower() + self.code += self.space + self.space + self.code += 'self.isAsync = "%s"\n' % str(self.cmd.async).lower() for req in self.cmd.request: if req.desc is not None: - self.code += self.space + self.space + '"""%s"""\n'%req.desc + self.code += self.space + self.space + '"""%s"""\n' % req.desc if req.required == "true": self.code += self.space + self.space + '"""Required"""\n' @@ -128,7 +134,8 @@ class codeGenerator: if req.type == "list" or req.type == "map": value = "[]" - self.code += self.space + self.space + 'self.%s = %s\n'%(req.name,value) + self.code += self.space + self.space + self.code += 'self.%s = %s\n' % (req.name, value) if req.required == "true": self.required.append(req.name) @@ -138,30 +145,33 @@ class codeGenerator: self.code += "]\n" self.required = [] - """generate response code""" subItems = {} self.code += "\n" - self.code += 'class %sResponse (baseResponse):\n'%self.cmd.name + 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 + self.code += self.space + self.space + self.code += '"""%s"""\n' % res.desc if len(res.subProperties) > 0: - self.code += self.space + self.space + 'self.%s = []\n'%res.name + self.code += self.space + self.space + self.code += '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 += self.space + self.space + self.code += '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 = open(self.outputFolder + "/cloudstackAPI/%s.py" % self.cmd.name, + "w") fp.write(self.code) fp.close() self.code = "" @@ -180,20 +190,26 @@ class codeGenerator: body += "\n" body += self.space + 'def __copy__(self):\n' - body += self.space + self.space + 'return CloudStackAPIClient(copy.copy(self.connection))\n' + body += self.space + self.space + body += 'return CloudStackAPIClient(copy.copy(self.connection))\n' body += "\n" for cmdName in self.cmdsName: - body += self.space + 'def %s(self, command, method="GET"):\n'%cmdName - body += self.space + self.space + 'response = %sResponse()\n'%cmdName - body += self.space + self.space + 'response = self.connection.marvin_request(command, response_type=response, method=method)\n' + body += self.space + body += 'def %s(self, command, method="GET"):\n' % cmdName + body += self.space + self.space + body += 'response = %sResponse()\n' % cmdName + body += self.space + self.space + body += 'response = self.connection.marvin_request(command,' + body += ' response_type=response, method=method)\n' body += self.space + self.space + 'return response\n' body += '\n' - imports += 'from %s import %sResponse\n'%(cmdName, cmdName) - initCmdsList += '"%s",'%cmdName + imports += 'from %s import %sResponse\n' % (cmdName, cmdName) + initCmdsList += '"%s",' % cmdName - fp = open(self.outputFolder + '/cloudstackAPI/cloudstackAPIClient.py', 'w') + fp = open(self.outputFolder + '/cloudstackAPI/cloudstackAPIClient.py', + 'w') fp.write(self.license) for item in [header, imports, body]: fp.write(item) @@ -224,11 +240,14 @@ class codeGenerator: def constructResponseFromXML(self, response): paramProperty = cmdParameterProperty() paramProperty.name = getText(response.getElementsByTagName('name')) - paramProperty.desc = getText(response.getElementsByTagName('description')) + 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'): + argList = response.getElementsByTagName('arguments')[0].\ + getElementsByTagName('arg') + for subresponse in argList: subProperty = self.constructResponseFromXML(subresponse) paramProperty.subProperties.append(subProperty) return paramProperty @@ -248,10 +267,13 @@ class codeGenerator: if async: csCmd.async = async - for param in cmd.getElementsByTagName("request")[0].getElementsByTagName("arg"): + argList = cmd.getElementsByTagName("request")[0].\ + getElementsByTagName("arg") + for param in argList: paramProperty = cmdParameterProperty() - paramProperty.name = getText(param.getElementsByTagName('name')) + paramProperty.name =\ + getText(param.getElementsByTagName('name')) assert paramProperty.name required = param.getElementsByTagName('required') @@ -288,18 +310,19 @@ class codeGenerator: def constructResponseFromJSON(self, response): paramProperty = cmdParameterProperty() - if response.has_key('name'): + if 'name' in response: paramProperty.name = response['name'] - assert paramProperty.name, "%s has no property name"%response + assert paramProperty.name, "%s has no property name" % response - if response.has_key('description'): + if 'description' in response: paramProperty.desc = response['description'] - if response.has_key('type'): + if 'type' in response: if response['type'] in ['list', 'map', 'set']: #Here list becomes a subproperty - if response.has_key('response'): + if 'response' in response: for innerResponse in response['response']: - subProperty = self.constructResponseFromJSON(innerResponse) + subProperty =\ + self.constructResponseFromJSON(innerResponse) paramProperty.subProperties.append(subProperty) paramProperty.type = response['type'] return paramProperty @@ -311,45 +334,45 @@ class codeGenerator: jsonOut = apiStream.readlines() assert len(jsonOut) > 0 apiDict = json.loads(jsonOut[0]) - if not apiDict.has_key('listapisresponse'): + if not 'listapisresponse' in apiDict: raise Exception("API discovery plugin response failed") - if not apiDict['listapisresponse'].has_key('count'): + if not 'count' in apiDict['listapisresponse']: raise Exception("Malformed api response") apilist = apiDict['listapisresponse']['api'] cmds = [] for cmd in apilist: csCmd = cloudStackCmd() - if cmd.has_key('name'): + if 'name' in cmd: csCmd.name = cmd['name'] assert csCmd.name - if cmd.has_key('description'): + if 'description' in cmd: csCmd.desc = cmd['description'] - if cmd.has_key('isasync'): + if 'isasync' in cmd: csCmd.async = cmd['isasync'] for param in cmd['params']: paramProperty = cmdParameterProperty() - if param.has_key('name'): + if 'name' in param: paramProperty.name = param['name'] assert paramProperty.name - if param.has_key('required'): + if 'required' in param: paramProperty.required = param['required'] - if param.has_key('description'): + if 'description' in param: paramProperty.desc = param['description'] - if param.has_key('type'): + if 'type' in param: paramProperty.type = param['type'] csCmd.request.append(paramProperty) for response in cmd['response']: - #FIXME: ExtractImage related APIs return empty dicts in response + #FIXME: ExtractImage related APIs return empty dicts in response if len(response) > 0: paramProperty = self.constructResponseFromJSON(response) csCmd.response.append(paramProperty) @@ -359,7 +382,8 @@ class codeGenerator: def generateCodeFromJSON(self, endpointUrl): """ - Api Discovery plugin returns the supported APIs of a CloudStack endpoint. + Api Discovery plugin returns the supported APIs of a CloudStack + endpoint. @return: The classes in cloudstackAPI/ formed from api discovery json """ if endpointUrl.find('response=json') >= 0: @@ -369,30 +393,34 @@ class codeGenerator: 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 path to the generated code entities, default is .") + help="The path to the generated code entities, 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") + help="The path and name of the api spec xml file,\ + default is /etc/cloud/cli/commands.xml") parser.add_option("-e", "--endpoint", dest="endpoint", - help="The endpoint mgmt server (with open 8096) where apis are discovered, default is localhost") + help="The endpoint mgmt server (with open 8096) where\ + apis are discovered, default is localhost") (options, args) = parser.parse_args() folder = "." if options.output is not None: folder = options.output - apiModule=folder + "/cloudstackAPI" + 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 "Failed to create folder %s, due to %s" % (apiModule, + sys.exc_info()) print parser.print_help() exit(2) @@ -400,7 +428,7 @@ if __name__ == "__main__": 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 "the spec file %s does not exists" % apiSpecFile print parser.print_help() exit(1) @@ -408,5 +436,6 @@ if __name__ == "__main__": if options.spec is not None: cg.generateCodeFromXML(apiSpecFile) elif options.endpoint is not None: - endpointUrl='http://%s:8096/client/api?command=listApis&response=json'%options.endpoint + endpointUrl = 'http://%s:8096/client/api?command=listApis&\ +response=json' % options.endpoint cg.generateCodeFromJSON(endpointUrl)