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')
317 self.task.keywords.append(keyword.strip())
322 def _process_params(self):
323 """!Process parameters
325 for p
in self.root.findall(
'parameter'):
327 node_gisprompt = p.find(
'gisprompt')
329 age = element = prompt =
None
330 if node_gisprompt
is not None:
332 age = node_gisprompt.get(
'age',
'')
333 element = node_gisprompt.get(
'element',
'')
334 prompt = node_gisprompt.get(
'prompt',
'')
339 node_values = p.find(
'values')
340 if node_values
is not None:
341 for pv
in node_values.findall(
'value'):
345 values_desc.append(desc)
349 node_key_desc = p.find(
'keydesc')
350 if node_key_desc
is not None:
351 for ki
in node_key_desc.findall(
'item'):
352 key_desc.append(ki.text)
354 if p.get(
'multiple',
'no') ==
'yes':
358 if p.get(
'required',
'no') ==
'yes':
363 if self.task.blackList[
'enabled']
and \
364 self.task.name
in self.task.blackList[
'items']
and \
365 p.get(
'name')
in self.task.blackList[
'items'][self.task.name].get(
'params', []):
370 self.task.params.append( {
371 "name" : p.get(
'name'),
372 "type" : p.get(
'type'),
373 "required" : required,
374 "multiple" : multiple,
377 'gisprompt' : gisprompt,
385 "values_desc" : values_desc,
387 "key_desc" : key_desc,
391 def _process_flags(self):
394 for p
in self.root.findall(
'flag'):
395 if self.task.blackList[
'enabled']
and \
396 self.task.name
in self.task.blackList[
'items']
and \
397 p.get(
'name')
in self.task.blackList[
'items'][self.task.name].get(
'flags', []):
402 if p.find(
'suppress_required')
is not None:
403 suppress_required =
True
405 suppress_required =
False
407 self.task.flags.append( {
408 "name" : p.get(
'name'),
412 "suppress_required" : suppress_required,
417 def _get_node_text(self, node, tag, default = ''):
421 return string.join(string.split(p.text),
' ')
426 """!Get grassTask instance"""
430 """!Returns the XML description for the GRASS cmd.
432 The DTD must be located in $GISBASE/etc/grass-interface.dtd,
433 otherwise the parser will not succeed.
435 @param cmd command (name of GRASS module)
438 if sys.platform ==
'win32' and os.path.splitext(cmd)[1] ==
'.py':
439 os.chdir(os.path.join(os.getenv(
'GISBASE'),
'etc',
'gui',
'scripts'))
440 args = [sys.executable, cmd,
'--interface-description']
442 args = [cmd,
'--interface-description']
444 p =
Popen(args, stdout = PIPE, stderr = PIPE)
445 cmdout, cmderr = p.communicate()
446 if p.returncode != 0:
447 raise ScriptError, _(
"Unable to fetch interface description for command '%(cmd)s'."
448 "\n\nDetails: %(det)s") % {
'cmd' : cmd,
'det' :
decode(cmderr) }
450 raise ScriptError, _(
"Unable to fetch interface description for command '%(cmd)s'."
451 "\n\nDetails: %(det)s") % {
'cmd' : cmd,
'det' : e }
457 return cmdout.replace(
'grass-interface.dtd', os.path.join(os.getenv(
'GISBASE'),
'etc',
'grass-interface.dtd'))
460 """!Parse interface of given GRASS module
462 @param name name of GRASS module to be parsed
464 enc = locale.getdefaultlocale()[1]
465 if enc
and enc.lower() ==
"cp932":
466 p = re.compile(
'encoding="' + enc +
'"', re.IGNORECASE)
467 tree = etree.fromstring(p.sub(
'encoding="utf-8"',
472 return parser(tree, blackList = blackList).get_task()
475 """!Returns meta information for any GRASS command as dictionary
476 with entries for description, keywords, usage, flags, and
480 >>> gtask.command_info('g.tempfile')
482 {'keywords': ['general', 'map management'],
483 'params': [{'gisprompt': False, 'multiple': False, 'name': 'pid', 'guidependency': '',
484 'default': '', 'age': None, 'required': True, 'value': '',
485 'label': '', 'guisection': '', 'key_desc': [], 'values': [], 'values_desc': [],
486 'prompt': None, 'hidden': False, 'element': None, 'type': 'integer',
487 'description': 'Process id to use when naming the tempfile'}],
488 'flags': [{'description': 'Verbose module output', 'value': False, 'label': '', 'guisection': '',
489 'suppress_required': False, 'hidden': False, 'name': 'verbose'}, {'description': 'Quiet module output',
490 'value': False, 'label': '', 'guisection': '', 'suppress_required': False, 'hidden': False, 'name': 'quiet'}],
491 'description': 'Creates a temporary file and prints the file name.',
492 'usage': 'g.tempfile pid=integer [--verbose] [--quiet]'
495 >>> gtask.command_info('v.buffer')['keywords']
497 ['vector', 'geometry', 'buffer']
503 cmdinfo[
'description'] = task.get_description()
504 cmdinfo[
'keywords'] = task.get_keywords()
505 cmdinfo[
'flags'] = flags = task.get_options()[
'flags']
506 cmdinfo[
'params'] = params = task.get_options()[
'params']
508 usage = task.get_name()
512 fname = f.get(
'name',
'unknown')
514 flags_long.append(fname)
516 flags_short.append(fname)
518 if len(flags_short) > 1:
519 usage +=
' [-' +
''.join(flags_short) +
']'
522 ptype =
','.join(p.get(
'key_desc', []))
524 ptype = p.get(
'type',
'')
525 req = p.get(
'required',
False)
530 usage += p[
'name'] +
'=' + ptype
531 if p.get(
'multiple',
False):
532 usage +=
'[,' + ptype +
',...]'
536 for key
in flags_long:
537 usage +=
' [--' + key +
']'
539 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.