3 # Copyright (C) 2010-2013 CEA/DEN
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 The Options class that manages the access to all options passed as
21 parameters in salomeTools command lines
28 from . import printcolors
31 import src.debug as DBG # Easy print stderr (for DEBUG only)
33 class OptResult(object):
35 An instance of this class will be the object manipulated
36 in code of all salomeTools commands
37 The aim of this class is to have an elegant syntax to manipulate the options.
40 | >> options, remainderArgs = command.parseArguments(args)
41 | >> print(options.output_verbose_level)
47 self.__dict__ = dict()
49 def __getattr__(self, name):
51 Overwrite of the __getattr__ function
52 to customize it for option usage
54 :param name: (str) The attribute to get the value.
55 :return: (str int list boolean level)
56 the value corresponding to the attribute.
58 if name in self.__dict__:
59 return self.__dict__[name]
61 raise AttributeError("--" + name + _(u" is not a valid option"))
63 def __setattr__(self, name, value):
65 Overwrite of the __setattr__ function
66 to customize it for option usage
68 :param name: (str) The attribute to set.
69 :param value: (str) The value corresponding to the attribute.
72 object.__setattr__(self, name, value)
75 aStr = PP.pformat(self.__dict__)
76 res = "%s(\n %s\n)" % (self.__class__.__name__, aStr[1:-1])
79 class Options(object):
81 Class to manage all salomeTools options
86 # The options field stocks all options of a command
87 # in a list that contains dicts
89 # The list of available option type
90 self.availableOptions = "noboolean boolean string int float long list list2 level".split()
91 self.noArgOptions = "noboolean boolean".split()
95 def add_option(self, shortName, longName, optionType, destName, helpString="", default=None):
97 Add an option to a command. It gets all attributes
98 of an option and append it in the options field
100 :param shortName: (str)
101 The short name of the option (as '-l' for level option).
102 :param longName: (str)
103 The long name of the option (as '--level' for level option).
104 :param optionType: (str) The type of the option (ex "int").
105 :param destName: (str) The name that will be used in the code.
106 :param helpString: (str)
107 The text to display when user ask for help on a command.
110 tmp = [o['shortName'] for o in self.options if o['shortName'] != '']
112 raise Exception("option '-%s' existing yet" % shortName)
113 tmp = [o['longName'] for o in self.options if o['longName'] != '']
115 raise Exception("option '--%s' existing yet" % longName)
118 option['shortName'] = shortName
119 option['longName'] = longName
121 if optionType not in self.availableOptions:
122 raise Exception("error optionType '%s' not available." % optionType)
124 option['optionType'] = optionType
125 option['destName'] = destName
126 option['helpString'] = helpString
127 option['result'] = default
129 self.options.append(option)
131 def getDetailOption(self, option):
135 :return: (tuple) 4-elements (shortName, longName, optionType, helpString)
137 oos = option['shortName']
138 ool = option['longName']
139 oot = option['optionType']
140 ooh = option['helpString']
141 return (oos, ool, oot, ooh)
145 Returns all options stored in self.options
146 as help message colored string
148 :return: (str) colored string
151 # Do nothing if there are no options
153 #there is -h option, always
154 #if len(self.options) == 0:
155 # return _("No available options.")
157 # for all options, gets its values.
158 # "shortname" is an mandatory field of the options, could be ''
159 msg += printcolors.printcHeader(_("Available options are:"))
160 for option in self.options:
161 oos, ool, oot, ooh = self.getDetailOption(option)
163 msg += "\n -%1s, --%s (%s)\n" % (oos, ool, oot)
165 msg += "\n --%s (%s)\n" % (ool, oot)
167 msg += "%s\n" % self.indent(ooh, 10)
170 def indent(self, text, amount, car=" "):
171 """indent multi lines message"""
172 padding = amount * car
173 return ''.join(padding + line for line in text.splitlines(True))
175 def parse_args(self, argList=None):
177 Instantiates the class OptResult
178 that gives access to all options in the code
180 :param argList: (list) the raw list of arguments that were passed
181 :return: (OptResult, list) as (optResult, args)
182 optResult is the option instance to manipulate in the code.
183 args is the full raw list of passed options
185 # see https://pymotw.com/2/getopt/
187 argList = sys.argv[1:]
189 DBG.write("parse_args", argList)
190 # DBG.write("options", self.options)
191 # format shortNameOption and longNameOption
192 # to make right arguments to getopt.getopt function
195 for option in self.options:
196 shortNameOption = shortNameOption + option['shortName']
197 if option['shortName'] != "" and option['optionType'] not in self.noArgOptions:
198 shortNameOption = shortNameOption + ":"
200 if option['longName'] != "":
201 if option['optionType'] not in self.noArgOptions:
202 longNameOption.append(option['longName'] + "=")
204 longNameOption.append(option['longName'])
206 # call to getopt.getopt function to get the option
207 # passed in the command regarding the available options
209 optlist, args = getopt.getopt(argList, shortNameOption, longNameOption)
210 except Exception as e:
211 msg = str(e) + " on '%s'\n\n" % " ".join(argList) + self.get_help()
214 # instantiate and completing the optResult that will be returned
215 optResult = OptResult()
216 for option in self.options:
217 shortOption = "-" + option['shortName']
218 longOption = "--" + option['longName']
219 optionType = option['optionType']
221 if opt[0] in [shortOption, longOption]:
222 if optionType == "string":
223 option['result'] = opt[1]
224 elif optionType == "boolean":
225 option['result'] = True
226 elif optionType == "noboolean":
227 option['result'] = False
228 elif optionType == "int":
229 option['result'] = int(opt[1])
230 elif optionType == "float":
231 option['result'] = float(opt[1])
232 elif optionType == "long":
233 option['result'] = long(opt[1])
234 elif optionType == "list":
235 if option['result'] is None:
236 option['result'] = list()
237 option['result'].append(opt[1])
238 elif optionType == "level": #logger logging levels
239 option['result'] = self.filterLevel(opt[1])
240 elif optionType == "list2":
241 if option['result'] is None:
242 option['result'] = list()
243 option['result'] = self.filterList2(opt[1])
245 optResult.__setattr__(option['destName'], option['result'])
246 # free the option in order to be able to make
247 # a new free call of options (API case)
248 option['result'] = None
250 self.results = {"optlist": optlist, "optResult": optResult, "args": args, "argList": argList}
251 DBG.write("results", self.results)
252 return optResult, args
254 def filterLevel(self, aLevel):
255 """filter level logging values"""
256 import src.loggingSimple as LOG
257 aLev = aLevel.upper()
258 knownLevels = LOG._knownLevels
259 maxLen = max([len(i) for i in knownLevels])
260 for i in range(maxLen):
261 for lev in knownLevels:
263 DBG.write("filterLevel", "%s -> %s" % (aLevel, lev))
265 msg = "Unknown level '%s', accepted are:\n%s" % (aLev, ", ".join(knownLevels))
268 def filterList2(self, aStr):
269 """filter a list as 'KERNEL,YACS,etc.'"""
270 aList = aStr.strip().split(",")
271 # fix list leading ',' as ',KERNEL,...'
272 aList = [i for i in aList if i != ""] # split old list leadin "," as ",KERNEL,ETC..."
278 repr for only self.options and self.results (if present)
280 aDict = {'options': self.options, 'results': self.results}
281 aStr = PP.pformat(aDict)
282 res = "%s(\n %s\n)" % (self.__class__.__name__, aStr[1:-1])
287 str for only resume expected self.options
289 #aDict = [(k["longName"], k["shortName", k["helpString"]) for k in self.options}
290 #aList = [(k, self.options[k]) for k in sorted(self.options.keys())]
292 for o in self.options:
293 aDict[o["longName"]] = (o["shortName"], o["helpString"])
294 aStr = PP.pformat(aDict)
295 res = "%s(\n %s)" % (self.__class__.__name__, aStr[1:-1])
298 def debug_write(self):
299 DBG.write("options and results", self, True)