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
152 if len(self.options) == 0:
153 return _("No available options.")
155 # for all options, gets its values.
156 # "shortname" is an mandatory field of the options, could be ''
157 msg += printcolors.printcHeader(_("Available options are:"))
158 for option in self.options:
159 oos, ool, oot, ooh = self.getDetailOption(option)
161 msg += "\n -%1s, --%s (%s)\n" % (oos, ool, oot)
163 msg += "\n --%s (%s)\n" % (ool, oot)
165 msg += "%s\n" % self.indent(ooh, 10)
168 def print_help(self):
170 Method that display all options stored in self.options and there help
174 print(self.get_help())
177 def indent(self, text, amount, car=" "):
178 """indent multi lines message"""
179 padding = amount * car
180 return ''.join(padding + line for line in text.splitlines(True))
182 def parse_args(self, argList=None):
184 Instantiates the class OptResult
185 that gives access to all options in the code
187 :param argList: (list) the raw list of arguments that were passed
188 :return: (OptResult, list) as (optResult, args)
189 optResult is the option instance to manipulate in the code.
190 args is the full raw list of passed options
192 # see https://pymotw.com/2/getopt/
194 argList = sys.argv[1:]
196 DBG.write("parse_args", argList)
197 # DBG.write("options", self.options)
198 # format shortNameOption and longNameOption
199 # to make right arguments to getopt.getopt function
202 for option in self.options:
203 shortNameOption = shortNameOption + option['shortName']
204 if option['shortName'] != "" and option['optionType'] not in self.noArgOptions:
205 shortNameOption = shortNameOption + ":"
207 if option['longName'] != "":
208 if option['optionType'] not in self.noArgOptions:
209 longNameOption.append(option['longName'] + "=")
211 longNameOption.append(option['longName'])
213 # call to getopt.getopt function to get the option
214 # passed in the command regarding the available options
216 optlist, args = getopt.getopt(argList, shortNameOption, longNameOption)
217 except Exception as e:
218 msg = str(e) + " on '%s'\n\n" % " ".join(argList) + self.get_help()
221 # instantiate and completing the optResult that will be returned
222 optResult = OptResult()
223 for option in self.options:
224 shortOption = "-" + option['shortName']
225 longOption = "--" + option['longName']
226 optionType = option['optionType']
228 if opt[0] in [shortOption, longOption]:
229 if optionType == "string":
230 option['result'] = opt[1]
231 elif optionType == "boolean":
232 option['result'] = True
233 elif optionType == "noboolean":
234 option['result'] = False
235 elif optionType == "int":
236 option['result'] = int(opt[1])
237 elif optionType == "float":
238 option['result'] = float(opt[1])
239 elif optionType == "long":
240 option['result'] = long(opt[1])
241 elif optionType == "list":
242 if option['result'] is None:
243 option['result'] = list()
244 option['result'].append(opt[1])
245 elif optionType == "level": #logger logging levels
246 option['result'] = self.filterLevel(opt[1])
247 elif optionType == "list2":
248 if option['result'] is None:
249 option['result'] = list()
250 option['result'] = self.filterList2(opt[1])
252 optResult.__setattr__(option['destName'], option['result'])
253 # free the option in order to be able to make
254 # a new free call of options (API case)
255 option['result'] = None
257 self.results = {"optlist": optlist, "optResult": optResult, "args": args, "argList": argList}
258 DBG.write("results", self.results)
259 return optResult, args
261 def filterLevel(self, aLevel):
262 """filter level logging values"""
263 import src.loggingSat as LOG
264 aLev = aLevel.upper()
265 knownLevels = LOG._knownLevels
266 maxLen = max([len(i) for i in knownLevels])
267 for i in range(maxLen):
268 for lev in knownLevels:
270 DBG.write("filterLevel", "%s -> %s" % (aLevel, lev))
272 msg = "Unknown level '%s', accepted are:\n%s" % (aLev, ", ".join(knownLevels))
275 def filterList2(self, aStr):
276 """filter a list as 'KERNEL,YACS,etc.'"""
277 aList = aStr.strip().split(",")
278 # fix list leading ',' as ',KERNEL,...'
279 aList = [i for i in aList if i != ""] # split old list leadin "," as ",KERNEL,ETC..."
285 repr for only self.options and self.results (if present)
287 aDict = {'options': self.options, 'results': self.results}
288 aStr = PP.pformat(aDict)
289 res = "%s(\n %s\n)" % (self.__class__.__name__, aStr[1:-1])
294 str for only resume expected self.options
296 #aDict = [(k["longName"], k["shortName", k["helpString"]) for k in self.options}
297 #aList = [(k, self.options[k]) for k in sorted(self.options.keys())]
299 for o in self.options:
300 aDict[o["longName"]] = (o["shortName"], o["helpString"])
301 aStr = PP.pformat(aDict)
302 res = "%s(\n %s)" % (self.__class__.__name__, aStr[1:-1])
305 def debug_write(self):
306 DBG.write("options and results", self, True)