1 """!@package grass.script.task
3 @brief GRASS Python scripting module (task)
5 Get interface description of GRASS commands
7 Based on gui/wxpython/gui_modules/menuform.py
12 from grass.script import task as gtask
14 gtask.command_info('r.info')
18 (C) 2011 by the GRASS Development Team
19 This program is free software under the GNU General Public
20 License (>=v2). Read the file COPYING that comes with GRASS
23 @author Martin Landa <landa.martin gmail.com>
29 import xml.etree.ElementTree
as etree
31 import elementtree.ElementTree
as etree
36 """!This class holds the structures needed for filling by the
39 Parameter blackList is a dictionary with fixed structure, eg.
42 blackList = {'items' : {'d.legend' : { 'flags' : ['m'],
48 @param blackList hide some options in the GUI (dictionary)
50 def __init__(self, path = None, blackList = None):
63 self.
blackList = {
'enabled' :
False,
'items' : {} }
69 except ScriptError, e:
75 """!Define first parameter
77 @return name of first parameter
85 """!Get error message ('' for no error)
95 """!Get module's description
97 @param full True for label + desc
108 """!Get module's keywords
113 """!Get list of parameters
115 @param element element name
119 params.append(p[element])
124 """!Get list of flags
126 @param element element name
130 flags.append(p[element])
134 def get_param(self, value, element = 'name', raiseError = True):
135 """!Find and return a param by name
137 @param value param's value
138 @param element element name
139 @param raiseError True for raise on error
146 if type(val)
in (types.ListType, types.TupleType):
149 elif type(val) == types.StringType:
150 if p[element][:len(value)] == value:
153 if p[element] == value:
159 raise ValueError, _(
"Parameter element '%(element)s' not found: '%(value)s'") % \
160 {
'element' : element,
'value' : value }
165 """!Find and return a flag by name
167 Raises ValueError when the flag is not found.
169 @param aFlag name of the flag
172 if f[
'name'] == aFlag:
174 raise ValueError, _(
"Flag not found: %s") % aFlag
177 """!Get error string produced by get_cmd(ignoreErrors = False)
179 @return list of errors
184 if f[
'value']
and f[
'suppress_required']:
188 if not p.get(
'value',
'')
and p.get(
'required',
False):
189 if not p.get(
'default',
''):
190 desc = p.get(
'label',
'')
192 desc = p[
'description']
193 errorList.append(_(
"Parameter '%(name)s' (%(desc)s) is missing.") % \
194 {
'name' : p[
'name'],
'desc' : desc })
198 def get_cmd(self, ignoreErrors = False, ignoreRequired = False, ignoreDefault = True):
199 """!Produce an array of command name and arguments for feeding
200 into some execve-like command processor.
202 @param ignoreErrors True to return whatever has been built so
203 far, even though it would not be a correct command for GRASS
204 @param ignoreRequired True to ignore required flags, otherwise
205 '<required>' is shown
206 @param ignoreDefault True to ignore parameters with default values
210 suppress_required =
False
211 for flag
in self.
flags:
213 if len(flag[
'name']) > 1:
214 cmd += [
'--' + flag[
'name'] ]
216 cmd += [
'-' + flag[
'name'] ]
217 if flag[
'suppress_required']:
218 suppress_required =
True
220 if p.get(
'value',
'') ==
'' and p.get(
'required',
False):
221 if p.get(
'default',
'') !=
'':
222 cmd += [
'%s=%s' % (p[
'name'], p[
'default']) ]
223 elif ignoreErrors
and not suppress_required
and not ignoreRequired:
224 cmd += [
'%s=%s' % (p[
'name'], _(
'<required>')) ]
225 elif p.get(
'value',
'') ==
'' and p.get(
'default',
'') !=
'' and not ignoreDefault:
226 cmd += [
'%s=%s' % (p[
'name'], p[
'default']) ]
227 elif p.get(
'value',
'') !=
'' and \
228 (p[
'value'] != p.get(
'default',
'')
or not ignoreDefault):
230 cmd += [
'%s=%s' % (p[
'name'], p[
'value']) ]
233 if ignoreErrors
is False and errList:
234 raise ValueError,
'\n'.join(errList)
241 return {
'flags' : self.
flags,
245 """!Check if command has at least one required paramater
248 if p.get(
'required',
False):
254 """!Set param value/values.
261 param[element] = aValue
263 def set_flag(self, aFlag, aValue, element = 'value'):
264 """!Enable / disable flag.
271 param[element] = aValue
274 """!Set flags and parameters
276 @param opts list of flags and parameters"""
279 self.
set_flag(opt.lstrip(
'-'),
True)
281 key, value = opt.split(
'=', 1)
285 """!A ElementTree handler for the --interface-description output,
286 as defined in grass-interface.dtd. Extend or modify this and the
287 DTD if the XML output of GRASS' parser is extended or modified.
289 @param tree root tree node
290 @param task grassTask instance or None
291 @param blackList list of flags/params to hide
293 @return grassTask instance
295 def __init__(self, tree, task = None, blackList = None):
301 self.task.blackList = blackList
308 self.task.define_first()
310 def _process_module(self):
311 """!Process module description
313 self.task.name = self.root.get(
'name', default =
'unknown')
316 if sys.platform ==
'win32' and self.task.name.endswith(
'.py'):
317 self.task.name = os.path.splitext(self.task.name)[0]
321 self.task.keywords.append(keyword.strip())
326 def _process_params(self):
327 """!Process parameters
329 for p
in self.root.findall(
'parameter'):
331 node_gisprompt = p.find(
'gisprompt')
333 age = element = prompt =
None
334 if node_gisprompt
is not None:
336 age = node_gisprompt.get(
'age',
'')
337 element = node_gisprompt.get(
'element',
'')
338 prompt = node_gisprompt.get(
'prompt',
'')
343 node_values = p.find(
'values')
344 if node_values
is not None:
345 for pv
in node_values.findall(
'value'):
349 values_desc.append(desc)
353 node_key_desc = p.find(
'keydesc')
354 if node_key_desc
is not None:
355 for ki
in node_key_desc.findall(
'item'):
356 key_desc.append(ki.text)
358 if p.get(
'multiple',
'no') ==
'yes':
362 if p.get(
'required',
'no') ==
'yes':
367 if self.task.blackList[
'enabled']
and \
368 self.task.name
in self.task.blackList[
'items']
and \
369 p.get(
'name')
in self.task.blackList[
'items'][self.task.name].get(
'params', []):
374 self.task.params.append( {
375 "name" : p.get(
'name'),
376 "type" : p.get(
'type'),
377 "required" : required,
378 "multiple" : multiple,
381 'gisprompt' : gisprompt,
389 "values_desc" : values_desc,
391 "key_desc" : key_desc,
395 def _process_flags(self):
398 for p
in self.root.findall(
'flag'):
399 if self.task.blackList[
'enabled']
and \
400 self.task.name
in self.task.blackList[
'items']
and \
401 p.get(
'name')
in self.task.blackList[
'items'][self.task.name].get(
'flags', []):
406 if p.find(
'suppress_required')
is not None:
407 suppress_required =
True
409 suppress_required =
False
411 self.task.flags.append( {
412 "name" : p.get(
'name'),
416 "suppress_required" : suppress_required,
421 def _get_node_text(self, node, tag, default = ''):
425 return string.join(string.split(p.text),
' ')
430 """!Get grassTask instance"""
434 """!Returns the XML description for the GRASS cmd.
436 The DTD must be located in $GISBASE/etc/grass-interface.dtd,
437 otherwise the parser will not succeed.
439 @param cmd command (name of GRASS module)
442 if sys.platform ==
'win32' and os.path.splitext(cmd)[1] ==
'.py':
443 os.chdir(os.path.join(os.getenv(
'GISBASE'),
'etc',
'gui',
'scripts'))
444 args = [sys.executable, cmd,
'--interface-description']
446 args = [cmd,
'--interface-description']
448 p =
Popen(args, stdout = PIPE, stderr = PIPE)
449 cmdout, cmderr = p.communicate()
450 if p.returncode != 0:
451 raise ScriptError, _(
"Unable to fetch interface description for command '%(cmd)s'."
452 "\n\nDetails: %(det)s") % {
'cmd' : cmd,
'det' :
decode(cmderr) }
454 raise ScriptError, _(
"Unable to fetch interface description for command '%(cmd)s'."
455 "\n\nDetails: %(det)s") % {
'cmd' : cmd,
'det' : e }
461 return cmdout.replace(
'grass-interface.dtd', os.path.join(os.getenv(
'GISBASE'),
'etc',
'grass-interface.dtd'))
464 """!Parse interface of given GRASS module
466 @param name name of GRASS module to be parsed
468 enc = locale.getdefaultlocale()[1]
469 if enc
and enc.lower() ==
"cp932":
470 p = re.compile(
'encoding="' + enc +
'"', re.IGNORECASE)
471 tree = etree.fromstring(p.sub(
'encoding="utf-8"',
476 return parser(tree, blackList = blackList).get_task()
479 """!Returns meta information for any GRASS command as dictionary
480 with entries for description, keywords, usage, flags, and
484 >>> gtask.command_info('g.tempfile')
486 {'keywords': ['general', 'map management'],
487 'params': [{'gisprompt': False, 'multiple': False, 'name': 'pid', 'guidependency': '',
488 'default': '', 'age': None, 'required': True, 'value': '',
489 'label': '', 'guisection': '', 'key_desc': [], 'values': [], 'values_desc': [],
490 'prompt': None, 'hidden': False, 'element': None, 'type': 'integer',
491 'description': 'Process id to use when naming the tempfile'}],
492 'flags': [{'description': 'Verbose module output', 'value': False, 'label': '', 'guisection': '',
493 'suppress_required': False, 'hidden': False, 'name': 'verbose'}, {'description': 'Quiet module output',
494 'value': False, 'label': '', 'guisection': '', 'suppress_required': False, 'hidden': False, 'name': 'quiet'}],
495 'description': 'Creates a temporary file and prints the file name.',
496 'usage': 'g.tempfile pid=integer [--verbose] [--quiet]'
499 >>> gtask.command_info('v.buffer')['keywords']
501 ['vector', 'geometry', 'buffer']
507 cmdinfo[
'description'] = task.get_description()
508 cmdinfo[
'keywords'] = task.get_keywords()
509 cmdinfo[
'flags'] = flags = task.get_options()[
'flags']
510 cmdinfo[
'params'] = params = task.get_options()[
'params']
512 usage = task.get_name()
516 fname = f.get(
'name',
'unknown')
518 flags_long.append(fname)
520 flags_short.append(fname)
522 if len(flags_short) > 1:
523 usage +=
' [-' +
''.join(flags_short) +
']'
526 ptype =
','.join(p.get(
'key_desc', []))
528 ptype = p.get(
'type',
'')
529 req = p.get(
'required',
False)
534 usage += p[
'name'] +
'=' + ptype
535 if p.get(
'multiple',
False):
536 usage +=
'[,' + ptype +
',...]'
540 for key
in flags_long:
541 usage +=
' [--' + key +
']'
543 cmdinfo[
'usage'] = usage
def define_first
Define first parameter.
def get_param
Find and return a param by name.
def _process_flags
Process flags.
def get_options
Get options.
def set_options
Set flags and parameters.
def get_description
Get module's description.
A ElementTree handler for the –interface-description output, as defined in grass-interface.dtd.
def get_cmd
Produce an array of command name and arguments for feeding into some execve-like command processor...
def get_cmd_error
Get error string produced by get_cmd(ignoreErrors = False)
def split
Platform spefic shlex.split.
def command_info
Returns meta information for any GRASS command as dictionary with entries for description, keywords, usage, flags, and parameters, e.g.
def _process_module
Process module description.
This class holds the structures needed for filling by the parser.
def get_interface_description
Returns the XML description for the GRASS cmd.
def get_task
Get grassTask instance.
def get_name
Get task name.
def get_keywords
Get module's keywords.
def _process_params
Process parameters.
def get_list_flags
Get list of flags.
def has_required
Check if command has at least one required paramater.
def parse_interface
Parse interface of given GRASS module.
def set_flag
Enable / disable flag.
def get_error_msg
Get error message ('' for no error)
def get_flag
Find and return a flag by name.
def parser
Interface to g.parser, intended to be run from the top-level, e.g.
def set_param
Set param value/values.
def _get_node_text
Get node text.
def get_list_params
Get list of parameters.