mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	* refactor: remove trailing whitespace from Python files * Add the GitHub Super-Linter Add Python flake8 linting for W291 trailing whitespace * Add licenses
		
			
				
	
	
		
			170 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Licensed to the Apache Software Foundation (ASF) under one
 | |
| # or more contributor license agreements.  See the NOTICE file
 | |
| # distributed with this work for additional information
 | |
| # regarding copyright ownership.  The ASF licenses this file
 | |
| # 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
 | |
| # KIND, either express or implied.  See the License for the
 | |
| # specific language governing permissions and limitations
 | |
| # under the License.
 | |
| 
 | |
| 
 | |
| 
 | |
| '''
 | |
| Created on Aug 2, 2010
 | |
| 
 | |
| '''
 | |
| 
 | |
| 
 | |
| import sys
 | |
| import os
 | |
| import inspect
 | |
| from optparse import OptionParser, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
 | |
| import cloudapis as apis
 | |
| 
 | |
| 
 | |
| def describe(name,desc):
 | |
|     def inner(decoratee):
 | |
|         if not hasattr(decoratee,"descriptions"): decoratee.descriptions = {}
 | |
|         decoratee.descriptions[name] = desc
 | |
|         return decoratee
 | |
|     return inner
 | |
| 
 | |
| 
 | |
| def error(msg):
 | |
|     sys.stderr.write(msg)
 | |
|     sys.stderr.write("\n")
 | |
| 
 | |
| 
 | |
| class MyOptionParser(OptionParser):
 | |
|     def error(self, msg):
 | |
|         error("%s: %s\n" % (self.get_prog_name(),msg))
 | |
|         self.print_usage(sys.stderr)
 | |
|         self.exit(os.EX_USAGE)
 | |
| 
 | |
|     def parse_args(self,*args,**kwargs):
 | |
|         options,arguments = OptionParser.parse_args(self,*args,**kwargs)
 | |
| 
 | |
|         def prune_options(options,alist):
 | |
|             """Given 'options' -- a list of arguments to OptionParser.add_option,
 | |
|             and a set of optparse Values, return a dictionary of only those values
 | |
|             that apply exclusively to 'options'"""
 | |
|             return dict( [ (k,getattr(options,k)) for k in dir(options) if k in alist ] )
 | |
| 
 | |
|         api_options = prune_options(options,self.api_dests)
 | |
|         cmd_options = prune_options(options,self.cmd_dests)
 | |
| 
 | |
|         return options,arguments,api_options,cmd_options
 | |
| 
 | |
| 
 | |
| def get_parser(api_callable=None,cmd_callable=None): # this should probably be the __init__ method of myoptionparser
 | |
| 
 | |
|     def getdefaulttag(default):
 | |
|         if default is not None: return " [Default: %default]"
 | |
|         return ''
 | |
| 
 | |
|     def get_arguments_and_options(callable):
 | |
|         """Infers and returns arguments and options based on a callable's signature.
 | |
|         Cooperates with decorator @describe"""
 | |
| 	try:
 | |
|         	funcargs = inspect.getargspec(callable).args
 | |
|         	defaults = inspect.getargspec(callable).defaults
 | |
| 	except:
 | |
| 		funcargs = inspect.getargspec(callable)[0]
 | |
|         	defaults = inspect.getargspec(callable)[3]
 | |
|         if not defaults: defaults = []
 | |
|         args = funcargs[1:len(funcargs)-len(defaults)] # this assumes self, so assumes methods
 | |
|         opts = funcargs[len(funcargs)-len(defaults):]
 | |
|         try: descriptions = callable.descriptions
 | |
|         except AttributeError: descriptions = {}
 | |
|         arguments = [ (argname, descriptions.get(argname,'') ) for argname in args ]
 | |
|         options = [ [
 | |
|                           ("--%s"%argname.replace("_","-"),),
 | |
|                           {
 | |
|                            "dest":argname,
 | |
|                            "help":descriptions.get(argname,'') + getdefaulttag(default),
 | |
|                            "default":default,
 | |
|                           }
 | |
|                         ] for argname,default in zip(opts,defaults) ]
 | |
|         return arguments,options
 | |
| 
 | |
|     basic_usage = "usage: %prog [options...] "
 | |
| 
 | |
|     api_name = "<api>"
 | |
|     cmd_name = "<command>"
 | |
|     description = "%prog is a command-line tool to access several cloud APIs."
 | |
|     arguments = ''
 | |
|     argexp = ""
 | |
| 
 | |
|     if api_callable:
 | |
|         api_name = api_callable.__module__.split(".")[-1].replace("_","-")
 | |
|         api_arguments,api_options = get_arguments_and_options(api_callable)
 | |
|         assert len(api_arguments) is 0 # no mandatory arguments for class initializers
 | |
| 
 | |
|     if cmd_callable:
 | |
|         cmd_name = cmd_callable.__name__.replace("_","-")
 | |
|         cmd_arguments,cmd_options = get_arguments_and_options(cmd_callable)
 | |
|         if cmd_arguments:
 | |
|             arguments   = " " + " ".join( [ s[0].upper() for s in cmd_arguments ] )
 | |
|             argexp = "\n\nArguments:\n" + "\n".join ( "  %s\n                        %s"%(s.upper(),u) for s,u in cmd_arguments )
 | |
|         description = cmd_callable.__doc__
 | |
| 
 | |
|     api_command = "%s %s"%(api_name,cmd_name)
 | |
| 
 | |
|     if description: description = "\n\n" + description
 | |
|     else: description = ''
 | |
| 
 | |
|     usage = basic_usage + api_command + arguments + description + argexp
 | |
| 
 | |
|     parser = MyOptionParser(usage=usage, add_help_option=False)
 | |
| 
 | |
|     parser.add_option('--help', action="help")
 | |
| 
 | |
|     group = parser.add_option_group("General options")
 | |
|     group.add_option('-v', '--verbose', dest="verbose", help="Print extra output")
 | |
| 
 | |
|     parser.api_dests = []
 | |
|     if api_callable and api_options:
 | |
|         group = parser.add_option_group("Options for the %s API"%api_name)
 | |
|         for a in api_options:
 | |
|             group.add_option(a[0][0],**a[1])
 | |
|             parser.api_dests.append(a[1]["dest"])
 | |
| 
 | |
|     parser.cmd_dests = []
 | |
|     if cmd_callable and cmd_options:
 | |
|         group = parser.add_option_group("Options for the %s command"%cmd_name)
 | |
|         for a in cmd_options:
 | |
|             group.add_option(a[0][0],**a[1])
 | |
|             parser.cmd_dests.append(a[1]["dest"])
 | |
| 
 | |
|     return parser
 | |
| 
 | |
| def lookup_command_in_api(api,command_name):
 | |
|     command = getattr(api,command_name.replace("-","_"),None)
 | |
|     return command
 | |
| 
 | |
| def get_api_list(api):
 | |
| 	apilist = []
 | |
| 	for cmd_name in dir(api):
 | |
| 		cmd = getattr(api,cmd_name)
 | |
|             	if callable(cmd) and not cmd_name.startswith("_"):
 | |
| 			apilist.append(cmd_name)
 | |
| 	return apilist
 | |
| 
 | |
| def get_command_list(api):
 | |
|         cmds = []
 | |
|         for cmd_name in dir(api):
 | |
|             cmd = getattr(api,cmd_name)
 | |
|             if callable(cmd) and not cmd_name.startswith("_"):
 | |
| 		if cmd.__doc__:docstring = cmd.__doc__
 | |
| 		else:docstring = ''
 | |
| 		cmds.append( "    %s" % (cmd_name.replace('_','-')) )
 | |
|         return cmds
 |