1 from __future__
import division, absolute_import
2 """A collection of structures for building python representations of parsed TCC commands.
6 Currently negation mixing for parameters can happen eg: 'Axis Init Azimuth, NoAltitude' is allowed.
7 This will have to be handled outside the parser. The parser sees Azimuth and NoAzimuth as
8 distinct keywords (not a negation of a single one). This choice simplifies the code because
9 I believe the only command with negatable parameters is Axis...but I could be wrong
12 __all__ = [
"Qualifier",
"Keyword",
"Command",
"SubCommand",
"CommandWrapper"]
19 """!Used to define a qualifier (which may have values associated).
24 numValueRange = [0,0],
31 @param[in] name string name of qualifier
32 @param[in] valType One of
33 1) None - in which case this is strictly a flag-type qualifier with no values
34 2) a callable function - which will cast any values to the
35 correct type for this qualifier
36 3) a list of strings - in which case this qualifier expects only values
37 belonging to this specific list.
38 @param[in] numValueRange [min, max] amount of values that may be associated
39 @param[in] defValueList if no values are explicitly indicated at parse time,
40 use these instead (must match valType!)
41 @param[in] help a help string
42 @param[in] negatable boolean. Whether or not a preceeding No is allowed when
43 specifying this qualifer. eg /Collimate vs. /NoCollimate
44 @param[in] defBoolValue boolean. If this qualifier is omitted by the user,
45 the resulting ParsedQualifier object will contain this boolean value (and
46 will additionally have the boolValueDefaulted flag set to True...).
52 defValueList = defValueList
or []
54 assert len(numValueRange) == 2
55 if numValueRange[1] !=
None:
56 numValueRange = [int(val)
for val
in numValueRange]
57 assert numValueRange[0] <= numValueRange[1]
62 assert numValueRange == [0,0]
63 assert defValueList == []
64 elif callable(valType):
67 defValueList = [
valType(val)
for val
in defValueList]
70 for keyword
in valType:
72 for val
in defValueList:
75 except Exception
as e:
76 raise CmdDefError(
'Poorly formed Qualifer construction: %s' % (e,))
87 strType = str(self.
valType).split(
"'")[1]
94 maxArgs =
'%s, *'%strType
95 if minArgs
and maxArgs:
97 argList =
' = (%s [,%s])' % (minArgs, maxArgs)
101 argList =
' [= %s]' % maxArgs
103 argList =
' [= (%s)]' % maxArgs
107 argList =
' = %s' % minArgs
109 argList =
' = (%s)' % minArgs
118 """!Print a help string
121 helpList.append(
'/%s%s' % (self.
name, self.
argList))
123 helpList.append(
' default: %s' % str(self.
defValueList))
124 nlSplit = [
' ' + x.strip()
for x
in self._help.split(
'\n')]
126 if hasattr(self.
valType,
'pop'):
127 helpList.append(
' Valid Keywords:')
129 helpList.append(
' %s' % kw)
133 """!A param is ultimately defined using a list of one or more of these
138 numValueRange =
None,
140 passMeByDefault=
False,
144 @param[in] name a string, will be used for unique abbreviation matching if not None
145 @param[in] castVals a callable, will cast any passed values to the correct type
146 @param[in] numValueRange [int, int] or [int, None]. Describes the max/min amount of acceptable values in valueList. If None, any amount of values are allowed
147 @param[in] defValueList a (possible empty) list of basic values to be passed by default if none were specified during parsing
148 @param[in] passMeByDefault a boolean. If True this param will be passed if a default is wanted
151 if numValueRange !=
None:
153 assert len(numValueRange) == 2
154 if numValueRange[1] !=
None:
155 numValueRange = [int(val)
for val
in numValueRange]
156 assert numValueRange[0] <= numValueRange[1]
158 int(numValueRange[0])
160 raise CmdDefError(
'numValueRange must be a 2 item list of integers ordered [low, high or None]')
162 if numValueRange != [0,0]:
164 assert callable(castVals)
166 raise CmdDefError(
'a cast function must be defined for values.')
170 if defValueList !=
None:
175 raise CmdDefError(
'Default value list cannot be casted correctly')
182 raise CmdDefError(
'Default value list outside allowed range of number of values')
192 """!For defining a single Keyword
197 numValueRange =
None,
199 passMeByDefault =
False,
203 @param[in] name a string, will be used for unique abbreviation matching if not None
204 @param[in] castVals a callable, will cast any passed values to the correct type
205 @param[in] numValueRange [int, int] or [int, None]. Describes the max/min amount of acceptable values in valueList. If None, any amount of values are allowed
206 @param[in] defValueList a (possible empty) list of basic values to be passed by default if none were specified during parsing
207 @param[in] passMeByDefault a boolean. If True this param will be passed if a default is wanted
208 @param[in] help a help string
210 ParamElement.__init__(self,
213 numValueRange = numValueRange,
214 defValueList = defValueList,
215 passMeByDefault = passMeByDefault,
220 """!One piece of a command that has been split on whitespace (and not commas nor equals sign..)
225 numParamRange = [1, 1] ,
229 @param[in] name a name for this param, used to index the parsed param dictionary
230 to be constructed at the time this is parsed.
231 @param[in] paramElementList a list of ParamElement objects
232 @param[in] numParamRange [int, int] or [int, None]. Describes the max/min amount
233 of acceptable params in paramList. If None,
234 any amount of params are allowed
235 @param[in] help a help string describing this parameter
239 assert len(numParamRange) == 2
240 if numParamRange[1] !=
None:
241 numParamRange = [int(val)
for val
in numParamRange]
242 assert numParamRange[0] <= numParamRange[1]
244 int(numParamRange[0])
246 raise CmdDefError(
'numParamRange must be a 2 item list of integers ordered [low, high or None]')
249 uniqueNames = [par.name
for par
in paramElementList]
250 if None in uniqueNames:
253 for name
in uniqueNames:
256 raise CmdDefError(
'For a given parameter, all values must either be named or not named; a mix is unacceptable.')
265 """!Which params to pass by default for this slot?
272 raise NotImplementedError(
'subclasses must override')
275 """!For defining a param slot expecting keywords and optionally values
277 def __init__(self, name, keywordDefList, numParamRange = [1,1], help=''):
278 """ @param[in] name a name for this param
279 @param[in] keywordDefList a list of Keyword objects, be sure to specify any
280 wanted as defaults specifically
281 @param[in] numParamRange number of keywords that may be passed jointly
282 @param[in] help a help string
284 ParamBase.__init__(self,
286 paramElementList = keywordDefList,
287 numParamRange = numParamRange,
292 minArgs =
', '.join([strType]*valRange[0])
293 if valRange[1] !=
None:
294 maxArgs =
', '.join([strType]*(valRange[1]-valRange[0]))
296 maxArgs =
'%s, *'%strType
297 if minArgs
and maxArgs:
299 argList =
'%s [,%s]' % (minArgs, maxArgs)
302 argList =
'[%s]' % maxArgs
305 argList =
'%s' % minArgs
315 helpList.append(
'%s: %s' % (self.
name, self.
argList))
316 nlSplit = [x.strip()
for x
in self._help.split(
'\n')]
318 nlSplit = [
' ' + x
for x
in nlSplit]
321 helpList.append(
' Default: %s' % str([x.name
for x
in self.
defaultParamList]))
322 helpList.append(
' Valid Keywords:')
326 if kw.castVals !=
None:
327 strType = str(kw.castVals).split(
"'")[1]
328 kwArgs = self.
getArgs(strType = strType, valRange = kw.numValueRange)
329 kwHelp.append(
' %s = %s'%(kwName, kwArgs))
332 kwHelp.append(
' %s' % kwName)
334 kwHelp.append(
' default: %s'% str(kw.defValueList))
336 kwHelp.append(
' %s'% str(kw.help))
342 """!Represents a list of type castVals
344 def __init__(self, name, castVals, numValueRange=[1,1], defValueList = None, help = 'help'):
346 @param[in] name a name for this param
347 @param[in] castVals a callable, will cast any passed values to the correct type
348 @param[in] numValueRange [int, int] or [int, None]. Describes the max/min amount of acceptable values in valueList. If None, any amount of values are allowed
349 @param[in] defValueList a (possible empty) list of basic values to be passed by default if none were specified during parsing
350 @param[in] help a help string
352 passMeByDefault =
True if defValueList
is not None else False
356 numValueRange = numValueRange,
357 defValueList = defValueList,
358 passMeByDefault = passMeByDefault,
360 ParamBase.__init__(self,
362 paramElementList = paramElementList,
370 minArgs =
', '.join([valType]*valRange[0])
371 if valRange[1] !=
None:
372 maxArgs =
', '.join([valType]*(valRange[1]-valRange[0]))
374 maxArgs =
'%s, *'%valType
375 if minArgs
and maxArgs:
377 argList =
'%s [,%s]' % (minArgs, maxArgs)
380 argList =
'[%s]' % maxArgs
383 argList =
'%s' % minArgs
389 helpList.append(
'%s: %s' % (self.
name, self.
argList))
390 nlSplit = [x.strip()
for x
in self._help.split(
'\n')]
392 nlSplit = [
' ' + x
for x
in nlSplit]
395 helpList.append(
' Default: %s' % str(self.
defaultParamList[0].defValueList))
399 """!For defining a command
401 def __init__(self, name, paramList=None, qualifierList=None, help='', callFunc=None, minParAmt=0):
403 @param[in] name command name
404 @param[in] paramList list of parameters (ParamBase objects) in the expected order, or None if no parameters
405 @param[in] qualifierList list of qualifiers (Qualifier objects), or None if no qualifiers
406 @param[in] help help string
407 @param[in] callFunc function to call that takes parsed command as an argument
408 @param[in] minParAmt the minimum number of arguments requried for this command
418 """!Return full help as a list of strings
424 dataList.append(
"Parameters:")
426 for helpLine
in param.help:
427 dataList.append(
" %s" % (helpLine,))
430 dataList.append(
"Qualifiers:")
432 for helpLine
in qual.help:
433 dataList.append(
" %s" % (helpLine))
437 """!Return brief help as a list of strings
441 if self.
name !=
None:
442 line1 += self.name.upper() +
' '
443 line1 +=
' '.join([x.name
for x
in self.
paramList])
444 dataList.append(line1)
445 dataList.append(
' ' + self.
help)
451 """!First paramSlot has the name of this subcommand. Used for cases where sub commands
452 of a command require unique parsing.
457 qualifierList =
None,
463 @param[in] selfKeyword a Keyword object
464 @param[in] paramList list of any additional parameters (ParamBase objects) in the expected order, or None if no parameters
465 @param[in] qualifierList list of qualifiers (Qualifier objects), or None if no qualifiers
466 @param[in] help help string
467 @param[in] callFunc function to call that takes parsed command as an argument
468 @param[in] minParAmt the minimum number of arguments requried for this command
472 paramList = paramList
or []
474 paramList = [
KeywordParam(name = selfKeyword.name, keywordDefList=[selfKeyword])] + paramList
476 Command.__init__(self,
478 paramList = paramList,
479 qualifierList = qualifierList,
482 minParAmt = minParAmt,
487 """!An outer wrapper for commands with alternate parsing syntaxes, eg 'SET'
495 @param[in] name command name (eg 'set')
496 @param[in] subCmdList a list of SubCommand objects providing definitions for alternate command
498 @param[in] help help string
506 """!Return full help as a list of strings
510 subList = subCmd.getFullHelp()
511 subList[0] = self.name.upper() +
" " + subList[0]
516 """!Return brief help as a list of strings
520 subList = subCmd.getBriefHelp()
521 subList[0] = self.name.upper() +
" " + subList[0]
def getFullHelp
Return full help as a list of strings.
Used to define a qualifier (which may have values associated).
def getBriefHelp
Return brief help as a list of strings.
First paramSlot has the name of this subcommand.
A param is ultimately defined using a list of one or more of these.
Represents a list of type castVals.
An outer wrapper for commands with alternate parsing syntaxes, eg 'SET'.
For defining a single Keyword.
def help
Print a help string.
For defining a param slot expecting keywords and optionally values.
def getFullHelp
Return full help as a list of strings.
One piece of a command that has been split on whitespace (and not commas nor equals sign...
def defaultParamList
Which params to pass by default for this slot?
def getBriefHelp
Return brief help as a list of strings.