1 """!@package grass.script.core 
    3 @brief GRASS Python scripting module (core functions) 
    5 Core functions to be used in Python scripts. 
   10 from grass.script import core as grass 
   16 (C) 2008-2011 by the GRASS Development Team 
   17 This program is free software under the GNU General Public 
   18 License (>=v2). Read the file COPYING that comes with GRASS 
   21 @author Glynn Clements 
   22 @author Martin Landa <landa.martin gmail.com> 
   23 @author Michael Barton <michael.barton asu.edu> 
   38 gettext.install(
'grasslibs', os.path.join(os.getenv(
"GISBASE"), 
'locale'), unicode=
True)
 
   43     def __init__(self, args, bufsize = 0, executable = None,
 
   44                  stdin = 
None, stdout = 
None, stderr = 
None,
 
   45                  preexec_fn = 
None, close_fds = 
False, shell = 
None,
 
   46                  cwd = 
None, env = 
None, universal_newlines = 
False,
 
   47                  startupinfo = 
None, creationflags = 0):
 
   50             shell = (sys.platform == 
"win32")
 
   52         subprocess.Popen.__init__(self, args, bufsize, executable,
 
   53                                   stdin, stdout, stderr,
 
   54                                   preexec_fn, close_fds, shell,
 
   55                                   cwd, env, universal_newlines,
 
   56                                   startupinfo, creationflags)
 
   58 PIPE = subprocess.PIPE
 
   59 STDOUT = subprocess.STDOUT
 
   68 raise_on_error = 
False  
   72     return Popen(*args, **kwargs).wait()
 
   76 _popen_args = [
"bufsize", 
"executable", 
"stdin", 
"stdout", 
"stderr",
 
   77                "preexec_fn", 
"close_fds", 
"cwd", 
"env",
 
   78                "universal_newlines", 
"startupinfo", 
"creationflags"]
 
   81     enc = locale.getdefaultlocale()[1]
 
   83         return string.decode(enc)
 
   88     if isinstance(val, types.StringType) 
or \
 
   89             isinstance(val, types.UnicodeType):
 
   91     if isinstance(val, types.ListType):
 
   92         return ",".join(map(_make_val, val))
 
   93     if isinstance(val, types.TupleType):
 
   94         return _make_val(list(val))
 
   97 def make_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **options):
 
   98     """!Return a list of strings suitable for use as the args parameter to 
   99     Popen() or call(). Example: 
  102     >>> grass.make_command("g.message", flags = 'w', message = 'this is a warning') 
  103     ['g.message', '-w', 'message=this is a warning'] 
  106     @param prog GRASS module 
  107     @param flags flags to be used (given as a string) 
  108     @param overwrite True to enable overwriting the output (<tt>--o</tt>) 
  109     @param quiet True to run quietly (<tt>--q</tt>) 
  110     @param verbose True to run verbosely (<tt>--v</tt>) 
  111     @param options module's parameters 
  113     @return list of arguments 
  125         args.append(
"-%s" % flags)
 
  126     for opt, val 
in options.iteritems():
 
  130             args.append(
"%s=%s" % (opt, _make_val(val)))
 
  133 def start_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **kwargs):
 
  134     """!Returns a Popen object with the command created by make_command. 
  135     Accepts any of the arguments which Popen() accepts apart from "args" 
  139     >>> p = grass.start_command("g.gisenv", stdout = subprocess.PIPE) 
  141     <subprocess.Popen object at 0xb7c12f6c> 
  142     >>> print p.communicate()[0] 
  143     GISDBASE='/opt/grass-data'; 
  144     LOCATION_NAME='spearfish60'; 
  146     GRASS_DB_ENCODING='ascii'; 
  151     @param prog GRASS module 
  152     @param flags flags to be used (given as a string) 
  153     @param overwrite True to enable overwriting the output (<tt>--o</tt>) 
  154     @param quiet True to run quietly (<tt>--q</tt>) 
  155     @param verbose True to run verbosely (<tt>--v</tt>) 
  156     @param kwargs module's parameters 
  162     for opt, val 
in kwargs.iteritems():
 
  163         if opt 
in _popen_args:
 
  167     args = 
make_command(prog, flags, overwrite, quiet, verbose, **options)
 
  168     if sys.platform == 
'win32' and os.path.splitext(prog)[1] == 
'.py':
 
  169         os.chdir(os.path.join(os.getenv(
'GISBASE'), 
'etc', 
'gui', 
'scripts'))
 
  170         args.insert(0, sys.executable)
 
  174         sys.stderr.write(
"D1/%d: %s.start_command(): %s\n" % (debug_level, __name__, 
' '.join(args)))
 
  177     return Popen(args, **popts)
 
  180     """!Passes all arguments to start_command(), then waits for the process to 
  181     complete, returning its exit code. Similar to subprocess.call(), but 
  182     with the make_command() interface. 
  184     @param args list of unnamed arguments (see start_command() for details) 
  185     @param kwargs list of named arguments (see start_command() for details) 
  187     @return exit code (0 for success) 
  193     """!Passes all arguments to start_command(), but also adds 
  194     "stdout = PIPE". Returns the Popen object. 
  197     >>> p = grass.pipe_command("g.gisenv") 
  199     <subprocess.Popen object at 0xb7c12f6c> 
  200     >>> print p.communicate()[0] 
  201     GISDBASE='/opt/grass-data'; 
  202     LOCATION_NAME='spearfish60'; 
  204     GRASS_DB_ENCODING='ascii'; 
  209     @param args list of unnamed arguments (see start_command() for details) 
  210     @param kwargs list of named arguments (see start_command() for details) 
  214     kwargs[
'stdout'] = PIPE
 
  218     """!Passes all arguments to start_command(), but also adds 
  219     "stdin = PIPE". Returns the Popen object. 
  221     @param args list of unnamed arguments (see start_command() for details) 
  222     @param kwargs list of named arguments (see start_command() for details) 
  226     kwargs[
'stdin'] = PIPE
 
  230     """!Passes all arguments to pipe_command, then waits for the process to 
  231     complete, returning its stdout (i.e. similar to shell `backticks`). 
  233     @param args list of unnamed arguments (see start_command() for details) 
  234     @param kwargs list of named arguments (see start_command() for details) 
  239     return ps.communicate()[0]
 
  242     """!Passes all arguments to read_command, then parses the output 
  245     Parsing function can be optionally given by <em>parse</em> parameter 
  246     including its arguments, e.g. 
  249     parse_command(..., parse = (grass.parse_key_val, { 'sep' : ':' })) 
  252     or you can simply define <em>delimiter</em> 
  255     parse_command(..., delimiter = ':') 
  258     @param args list of unnamed arguments (see start_command() for details) 
  259     @param kwargs list of named arguments (see start_command() for details) 
  261     @return parsed module output 
  265     if 'parse' in kwargs:
 
  266         if type(kwargs[
'parse']) 
is types.TupleType:
 
  267             parse = kwargs[
'parse'][0]
 
  268             parse_args = kwargs[
'parse'][1]
 
  271     if 'delimiter' in kwargs:
 
  272         parse_args = { 
'sep' : kwargs[
'delimiter'] }
 
  273         del kwargs[
'delimiter']
 
  276         parse = parse_key_val 
 
  280     return parse(res, **parse_args)
 
  283     """!Passes all arguments to feed_command, with the string specified 
  284     by the 'stdin' argument fed to the process' stdin. 
  286     @param args list of unnamed arguments (see start_command() for details) 
  287     @param kwargs list of named arguments (see start_command() for details) 
  291     stdin = kwargs[
'stdin']
 
  297 def exec_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, env = None, **kwargs):
 
  298     """!Interface to os.execvpe(), but with the make_command() interface. 
  300     @param prog GRASS module 
  301     @param flags flags to be used (given as a string) 
  302     @param overwrite True to enable overwriting the output (<tt>--o</tt>) 
  303     @param quiet True to run quietly (<tt>--q</tt>) 
  304     @param verbose True to run verbosely (<tt>--v</tt>) 
  305     @param env directory with environmental variables 
  306     @param kwargs module's parameters 
  309     args = 
make_command(prog, flags, overwrite, quiet, verbose, **kwargs)
 
  312     os.execvpe(prog, args, env)
 
  317     """!Display a message using `g.message` 
  319     @param msg message to be displayed 
  320     @param flag flags (given as string) 
  322     run_command(
"g.message", flags = flag, message = msg)
 
  325     """!Display a debugging message using `g.message -d` 
  327     @param msg debugging message to be displayed 
  328     @param debug debug level (0-5) 
  330     run_command(
"g.message", flags = 
'd', message = msg, debug = debug)
 
  333     """!Display a verbose message using `g.message -v` 
  335     @param msg verbose message to be displayed 
  340     """!Display an informational message using `g.message -i` 
  342     @param msg informational message to be displayed 
  347     """!Display a progress info message using `g.message -p` 
  350     message(_("Percent complete...")) 
  357     @param i current item 
  358     @param n total number of items 
  359     @param s increment size 
  361     message(
"%d %d %d" % (i, n, s), flag = 
'p')
 
  364     """!Display a warning message using `g.message -w` 
  366     @param msg warning message to be displayed 
  371     """!Display an error message using `g.message -e` 
  373     Raise exception when on_error is 'raise'. 
  375     @param msg error message to be displayed 
  377     global raise_on_error
 
  384     """!Display an error message using `g.message -e`, then abort 
  386     @param msg error message to be displayed 
  392     """!Define behaviour on error (error() called) 
  394     @param raise_exp True to raise ScriptError instead of calling 
  397     @return current status 
  399     global raise_on_error
 
  400     tmp_raise = raise_on_error
 
  401     raise_on_error = raise_exp
 
  405 def _parse_opts(lines):
 
  409         line = line.rstrip(
'\r\n')
 
  413             [var, val] = line.split(
'=', 1)
 
  415             raise SyntaxError(
"invalid output from g.parser: %s" % line)
 
  417         if var.startswith(
'flag_'):
 
  418             flags[var[5:]] = bool(int(val))
 
  419         elif var.startswith(
'opt_'):
 
  420             options[var[4:]] = val
 
  421         elif var 
in [
'GRASS_OVERWRITE', 
'GRASS_VERBOSE']:
 
  422             os.environ[var] = val
 
  424             raise SyntaxError(
"invalid output from g.parser: %s" % line)
 
  426     return (options, flags)
 
  429     """!Interface to g.parser, intended to be run from the top-level, e.g.: 
  432         if __name__ == "__main__": 
  433             options, flags = grass.parser() 
  437     Thereafter, the global variables "options" and "flags" will be 
  438     dictionaries containing option/flag values, keyed by lower-case 
  439     option/flag names. The values in "options" are strings, those in 
  440     "flags" are Python booleans. 
  442     if not os.getenv(
"GISBASE"):
 
  443         print >> sys.stderr, 
"You must be in GRASS GIS to run this program." 
  447     cmdline += [
'"' + arg + 
'"' for arg 
in sys.argv[1:]]
 
  448     os.environ[
'CMDLINE'] = 
' '.join(cmdline)
 
  452     if not os.path.isabs(name):
 
  453         if os.sep 
in name 
or (os.altsep 
and os.altsep 
in name):
 
  454             argv[0] = os.path.abspath(name)
 
  456             argv[0] = os.path.join(sys.path[0], name)
 
  458     p = 
Popen([
'g.parser', 
'-s'] + argv, stdout = PIPE)
 
  459     s = p.communicate()[0]
 
  460     lines = s.splitlines()
 
  462     if not lines 
or lines[0].rstrip(
'\r\n') != 
"@ARGS_PARSED@":
 
  464         sys.exit(p.returncode)
 
  466     return _parse_opts(lines[1:])
 
  471     """!Returns the name of a temporary file, created with g.tempfile.""" 
  472     return read_command(
"g.tempfile", pid = os.getpid()).strip()
 
  475     """!Returns the name of a temporary dir, created with g.tempfile.""" 
  476     tmp = 
read_command(
"g.tempfile", pid = os.getpid()).strip()
 
  483     """A general-purpose key-value store. 
  485     KeyValue is a subclass of dict, but also allows entries to be read and 
  486     written using attribute syntax. Example: 
  489     >>> region = grass.region() 
  506     """!Parse a string into a dictionary, where entries are separated 
  507     by newlines and the key and value are separated by `sep' (default: `=') 
  509     @param s string to be parsed 
  510     @param sep key/value separator 
  511     @param dflt default value to be used 
  512     @param val_type value type (None for no cast) 
  513     @param vsep vertical separator (default os.linesep) 
  515     @return parsed input (dictionary of keys/values) 
  523         lines = s.split(vsep)
 
  529         lines = s.splitlines()
 
  532         kv = line.split(sep, 1)
 
  539             result[k] = val_type(v)
 
  547     """!Returns the output from running g.gisenv (with no arguments), as a 
  551     >>> env = grass.gisenv() 
  552     >>> print env['GISDBASE'] 
  556     @return list of GRASS variables 
  562     """!Tests if location is lat/long. Value is obtained 
  563     by checking the "g.region -pu" projection code. 
  565     @return True for a lat/long region, False otherwise 
  569     if kv[
'projection'].
split(
' ')[1] == 
'3':
 
  577     """!Returns the output from running "g.region -gu", as a 
  580     \param region3d True to get 3D region 
  583     >>> region = grass.region() 
  584     >>> [region[key] for key in "nsew"] 
  585     [228500.0, 215000.0, 645000.0, 630000.0] 
  586     >>> (region['nsres'], region['ewres']) 
  590     @return dictionary of region values 
  598     for k 
in [
'rows',  
'cols',  
'cells',
 
  599               'rows3', 
'cols3', 
'cells3', 
'depths']:
 
  608     """!Returns region settings as a string which can used as 
  609     GRASS_REGION environmental variable. 
  611     If no 'kwargs' are given then the current region is used. Note 
  612     that this function doesn't modify the current region! 
  614     See also use_temp_region() for alternative method how to define 
  615     temporary region used for raster-based computation. 
  617     \param region3d True to get 3D region 
  618     \param kwargs g.region's parameters like 'rast', 'vect' or 'region' 
  620     os.environ['GRASS_REGION'] = grass.region_env(region = 'detail') 
  621     grass.mapcalc('map = 1', overwrite = True) 
  622     os.environ.pop('GRASS_REGION') 
  625     @return string with region values 
  626     @return empty string on error 
  630     windfile = os.path.join (env[
'GISDBASE'], env[
'LOCATION_NAME'],
 
  631                               env[
'MAPSET'], 
"WIND")
 
  632     fd = open(windfile, 
"r") 
  634     for line 
in fd.readlines():
 
  635         key, value = map(
lambda x: x.strip(), line.split(
":", 1))
 
  636         if kwargs 
and key 
not in (
'proj', 
'zone'):
 
  638         if not kwargs 
and not region3d 
and \
 
  639                 key 
in (
'top', 
'bottom', 
'cols3', 
'rows3',
 
  640                         'depths', 
'e-w resol3', 
'n-s resol3', 
't-b resol'):
 
  643         grass_region += 
'%s: %s;' % (key, value)
 
  658     kwdata = [(
'north',     
'n'),
 
  664               (
'e-w resol', 
'ewres'),
 
  665               (
'n-s resol', 
'nsres')]
 
  667         kwdata += [(
'top',        
't'),
 
  671                    (
'depths',     
'depths'),
 
  672                    (
'e-w resol3', 
'ewres3'),
 
  673                    (
'n-s resol3', 
'nsres3'),
 
  674                    (
't-b resol',  
'tbres')]
 
  676     for wkey, rkey 
in kwdata:
 
  677         grass_region += 
'%s: %s;' % (wkey, reg[rkey])
 
  682     """!Copies the current region to a temporary region with "g.region save=", 
  683     then sets WIND_OVERRIDE to refer to that region. Installs an atexit 
  684     handler to delete the temporary region upon termination. 
  686     name = 
"tmp.%s.%d" % (os.path.basename(sys.argv[0]), os.getpid())
 
  687     run_command(
"g.region", save = name, overwrite = 
True)
 
  688     os.environ[
'WIND_OVERRIDE'] = name
 
  689     atexit.register(del_temp_region)
 
  692     """!Unsets WIND_OVERRIDE and removes any region named by it.""" 
  694         name = os.environ.pop(
'WIND_OVERRIDE')
 
  695         run_command(
"g.remove", quiet = 
True, region = name)
 
  702     """!Returns the output from running g.findfile as a 
  706     >>> result = grass.find_file('fields', element = 'vector') 
  707     >>> print result['fullname'] 
  709     >>> print result['file'] 
  710     /opt/grass-data/spearfish60/PERMANENT/vector/fields 
  713     @param name file name 
  714     @param element element type (default 'cell') 
  715     @param mapset mapset name (default all mapsets in search path) 
  717     @return parsed output of g.findfile 
  719     s = 
read_command(
"g.findfile", flags=
'n', element = element, file = name, mapset = mapset)
 
  725     """!List elements grouped by mapsets. 
  727     Returns the output from running g.list, as a dictionary where the 
  728     keys are mapset names and the values are lists of maps in that 
  732     >>> grass.list_grouped('rast')['PERMANENT'] 
  733     ['aspect', 'erosion1', 'quads', 'soils', 'strm.dist', ... 
  736     @param type element type (rast, vect, rast3d, region, ...) 
  737     @param check_search_path True to add mapsets for the search path with no found elements 
  739     @return directory of mapsets/elements 
  741     dashes_re = re.compile(
"^----+$")
 
  742     mapset_re = re.compile(
"<(.*)>")
 
  744     if check_search_path:
 
  745         for mapset 
in mapsets(search_path = 
True):
 
  749     for line 
in read_command(
"g.list", type = type).splitlines():
 
  752         if dashes_re.match(line):
 
  754         m = mapset_re.search(line)
 
  757             if mapset 
not in result.keys():
 
  761             result[mapset].extend(line.split())
 
  772     """!List of elements as tuples. 
  774     Returns the output from running g.list, as a list of (map, mapset) 
  778     >>> grass.list_pairs('rast') 
  779     [('aspect', 'PERMANENT'), ('erosion1', 'PERMANENT'), ('quads', 'PERMANENT'), ... 
  782     @param type element type (rast, vect, rast3d, region, ...) 
  784     @return list of tuples (map, mapset) 
  786     return _concat([[(map, mapset) 
for map 
in maps]
 
  790     """!List of elements as strings. 
  792     Returns the output from running g.list, as a list of qualified 
  796     >>> grass.list_strings('rast') 
  797     ['aspect@PERMANENT', 'erosion1@PERMANENT', 'quads@PERMANENT', 'soils@PERMANENT', ... 
  800     @param type element type 
  802     @return list of strings ('map@@mapset') 
  804     return [
"%s@%s" % pair 
for pair 
in list_pairs(type)]
 
  809     """!List of elements as strings. 
  811     Returns the output from running g.mlist, as a list of qualified 
  814     @param type element type (rast, vect, rast3d, region, ...) 
  815     @param pattern pattern string 
  816     @param mapset mapset name (if not given use search path) 
  817     @param flag pattern type: 'r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
 
  819     @return list of elements
 
  822     for line in read_command("g.mlist",
 
  827                              mapset = mapset).splitlines():
 
  828         result.append(line.strip())
 
  832 def mlist_pairs(type, pattern = None, mapset = None, flag = ''):
 
  833     """!List of elements as pairs
 
  835     Returns the output from running g.mlist, as a list of
 
  838     @param type element type (rast, vect, rast3d, region, ...)
 
  839     @param pattern pattern string
 
  840     @param mapset mapset name (if not given use search path)
 
  841     @param flag pattern type: '
r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
 
  843     @return list of elements
 
  845     return [tuple(map.split('@', 1)) for map in mlist_strings(type, pattern, mapset, flag)]
 
  847 def mlist_grouped(type, pattern = None, check_search_path = True, flag = ''):
 
  848     """!List of elements grouped by mapsets.
 
  850     Returns the output from running g.mlist, as a dictionary where the
 
  851     keys are mapset names and the values are lists of maps in that
 
  855     >>> grass.mlist_grouped('rast', pattern='r*')['PERMANENT']
 
  856     ['railroads', 'roads', 'rstrct.areas', 'rushmore']
 
  859     @param type element type (rast, vect, rast3d, region, ...)
 
  860     @param pattern pattern string
 
  861     @param check_search_path True to add mapsets for the search path with no found elements
 
  862     @param flag pattern type: '
r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
 
  864     @return directory of mapsets/elements
 
  867     if check_search_path:
 
  868         for mapset in mapsets(search_path = True):
 
  872     for line in read_command("g.mlist", quiet = True, flags = "m" + flag,
 
  873                              type = type, pattern = pattern).splitlines():
 
  875             name, mapset = line.split('@')
 
  877             warning(_("Invalid element '%s'") % line)
 
  881             result[mapset].append(name) 
 
  883             result[mapset] = [name, ] 
 
  890     "white":   (1.00, 1.00, 1.00),
 
  891     "black":   (0.00, 0.00, 0.00),
 
  892     "red":     (1.00, 0.00, 0.00),
 
  893     "green":   (0.00, 1.00, 0.00),
 
  894     "blue":    (0.00, 0.00, 1.00),
 
  895     "yellow":  (1.00, 1.00, 0.00),
 
  896     "magenta": (1.00, 0.00, 1.00),
 
  897     "cyan":    (0.00, 1.00, 1.00),
 
  898     "aqua":    (0.00, 0.75, 0.75),
 
  899     "grey":    (0.75, 0.75, 0.75),
 
  900     "gray":    (0.75, 0.75, 0.75),
 
  901     "orange":  (1.00, 0.50, 0.00),
 
  902     "brown":   (0.75, 0.50, 0.25),
 
  903     "purple":  (0.50, 0.00, 1.00),
 
  904     "violet":  (0.50, 0.00, 1.00),
 
  905     "indigo":  (0.00, 0.50, 1.00)}
 
  907 def parse_color(val, dflt = None):
 
  908     """!Parses the string "val" as a GRASS colour, which can be either one of
 
  909     the named colours or an R:G:B tuple e.g. 255:255:255. Returns an
 
  910     (r,g,b) triple whose components are floating point values between 0
 
  914     >>> grass.parse_color("red")
 
  916     >>> grass.parse_color("255:0:0")
 
  920     @param val color value
 
  921     @param dflt default color value
 
  925     if val in named_colors:
 
  926         return named_colors[val]
 
  928     vals = val.split(':')
 
  930         return tuple(float(v) / 255 for v in vals)
 
  934 # check GRASS_OVERWRITE
 
  937     """!Return True if existing files may be overwritten"""
 
  938     owstr = 'GRASS_OVERWRITE'
 
  939     return owstr in os.environ and os.environ[owstr] != '0'
 
  941 # check GRASS_VERBOSE
 
  944     """!Return the verbosity level selected by GRASS_VERBOSE"""
 
  945     vbstr = os.getenv('GRASS_VERBOSE')
 
  951 ## various utilities, not specific to GRASS
 
  953 # basename inc. extension stripping
 
  955 def basename(path, ext = None):
 
  956     """!Remove leading directory components and an optional extension
 
  957     from the specified path
 
  962     name = os.path.basename(path)
 
  965     fs = name.rsplit('.', 1)
 
  966     if len(fs) > 1 and fs[1].lower() == ext:
 
  970 # find a program (replacement for "which")
 
  972 def find_program(pgm, args = []):
 
  973     """!Attempt to run a program, with optional arguments. 
 
  974     You must call the program in a way that will return a successful
 
  975     exit code. For GRASS modules this means you need to pass it some
 
  976     valid CLI option, like "--help". For other programs a common
 
  977     valid do-little option is "--version".
 
  982     >>> grass.find_program('r.sun', ['help'])
 
  984     >>> grass.find_program('gdalwarp', ['--version'])
 
  988     @param pgm program name
 
  989     @param args list of arguments
 
  991     @return False if the attempt failed due to a missing executable
 
  992             or non-zero return code
 
  993     @return True otherwise
 
  995     nuldev = file(os.devnull, 'w+')
 
  997         ret = call([pgm] + args, stdin = nuldev, stdout = nuldev, stderr = nuldev)
 
 1008 # try to remove a file, without complaints
 
 1010 def try_remove(path):
 
 1011     """!Attempt to remove a file; no exception is generated if the
 
 1014     @param path path to file to remove
 
 1021 # try to remove a directory, without complaints
 
 1023 def try_rmdir(path):
 
 1024     """!Attempt to remove a directory; no exception is generated if the
 
 1027     @param path path to directory to remove
 
 1032         shutil.rmtree(path, ignore_errors = True)
 
 1034 def float_or_dms(s):
 
 1035     """!Convert DMS to float.
 
 1041     return sum(float(x) / 60 ** n for (n, x) in enumerate(s.split(':')))
 
 1043 # interface to g.mapsets
 
 1045 def mapsets(search_path = False):
 
 1046     """!List available mapsets
 
 1048     @param searchPatch True to list mapsets only in search path
 
 1050     @return list of mapsets
 
 1056     mapsets = read_command('g.mapsets',
 
 1061         fatal(_("Unable to list mapsets"))
 
 1063     return mapsets.splitlines()
 
 1065 # interface to `g.proj -c`
 
 1067 def create_location(dbase, location,
 
 1068                     epsg = None, proj4 = None, filename = None, wkt = None,
 
 1069                     datum = None, datumtrans = None, desc = None):
 
 1070     """!Create new location
 
 1072     Raise ScriptError on error.
 
 1074     @param dbase path to GRASS database
 
 1075     @param location location name to create
 
 1076     @param epsg if given create new location based on EPSG code
 
 1077     @param proj4 if given create new location based on Proj4 definition
 
 1078     @param filename if given create new location based on georeferenced file
 
 1079     @param wkt if given create new location based on WKT definition (path to PRJ file)
 
 1080     @param datum GRASS format datum code
 
 1081     @param datumtrans datum transformation parameters (used for epsg and proj4)
 
 1082     @param desc description of the location (creates MYNAME file)
 
 1085     if epsg or proj4 or filename or wkt:
 
 1086         gisdbase = gisenv()['GISDBASE']
 
 1087         # FIXME: changing GISDBASE mid-session is not background-job safe
 
 1088         run_command('g.gisenv',
 
 1089                     set = 'GISDBASE=%s' % dbase)
 
 1090     if not os.path.exists(dbase):
 
 1095         kwargs['datum'] = datum
 
 1097         kwargs['datumtrans'] = datumtrans
 
 1100         ps = pipe_command('g.proj',
 
 1104                           location = location,
 
 1108         ps = pipe_command('g.proj',
 
 1112                           location = location,
 
 1116         ps = pipe_command('g.proj',
 
 1119                           location = location,
 
 1122         ps = pipe_command('g.proj',
 
 1125                           location = location,
 
 1128         _create_location_xy(dbase, location)
 
 1130     if epsg or proj4 or filename or wkt:
 
 1131         error = ps.communicate()[1]
 
 1132         run_command('g.gisenv',
 
 1133                     set = 'GISDBASE=%s' % gisdbase)
 
 1135         if ps.returncode != 0 and error:
 
 1136             raise ScriptError(repr(error))
 
 1139         fd = codecs.open(os.path.join(dbase, location,
 
 1140                                       'PERMANENT', 'MYNAME'),
 
 1141                          encoding = 'utf-8', mode = 'w')
 
 1143             fd.write(desc + os.linesep)
 
 1145             fd.write(os.linesep)
 
 1148         raise ScriptError(repr(e))
 
 1150 def _create_location_xy(database, location):
 
 1151     """!Create unprojected location
 
 1153     Raise ScriptError on error.
 
 1155     @param database GRASS database where to create new location
 
 1156     @param location location name
 
 1158     cur_dir = os.getcwd()
 
 1162         os.mkdir(os.path.join(location, 'PERMANENT'))
 
 1164         # create DEFAULT_WIND and WIND files
 
 1165         regioninfo = ['proj:       0',
 
 1184         defwind = open(os.path.join(location,
 
 1185                                     "PERMANENT", "DEFAULT_WIND"), 'w')
 
 1186         for param in regioninfo:
 
 1187             defwind.write(param + '%s' % os.linesep)
 
 1190         shutil.copy(os.path.join(location, "PERMANENT", "DEFAULT_WIND"),
 
 1191                     os.path.join(location, "PERMANENT", "WIND"))
 
 1195         raise ScriptError(repr(e))
 
 1197 # interface to g.version
 
 1200     """!Get GRASS version as dictionary
 
 1205     {'date': '2011', 'libgis_date': '2011-02-26 21:31:24 +0100 (Sat, 26 Feb 2011)',
 
 1206     'version': '6.5.svn', 'libgis_revision': '45467', 'revision': '47305'}
 
 1209     data = parse_command('g.version',
 
 1211     for k, v in data.iteritems():
 
 1212         data[k.strip()] = v.replace('"', '').strip()
 
 1217 if find_program('g.gisenv', ['--help']):
 
 1218     debug_level = int(gisenv().get('DEBUG', 0))
 
 1221     """!Checks if the string contains only allowed characters.
 
 1223     This is the Python implementation of G_legal_filename() function.
 
 1225     @note It is not clear when to use this function.
 
 1227     if not s or s[0] == '.':
 
 1228         warning(_("Illegal filename <%s>. Cannot be empty or start with '.'.") % s)
 
 1233                if c in '/"\'@,=*~' or c <= ' ' or c >= '\177']
 
 1235         illegal = ''.join(sorted(set(illegal)))
 
 1236         warning(_("Illegal filename <%s>. <%s> not allowed.\n") % (s, illegal))
 
def list_strings
List of elements as strings. 
 
def make_command
Return a list of strings suitable for use as the args parameter to Popen() or call(). 
 
def info
Display an informational message using g.message -i 
 
def list_grouped
List elements grouped by mapsets. 
 
def locn_is_latlong
Tests if location is lat/long. 
 
def parse_command
Passes all arguments to read_command, then parses the output by parse_key_val(). 
 
def use_temp_region
Copies the current region to a temporary region with "g.region save=", then sets WIND_OVERRIDE to ref...
 
def mlist_strings
List of elements as strings. 
 
def exec_command
Interface to os.execvpe(), but with the make_command() interface. 
 
def feed_command
Passes all arguments to start_command(), but also adds "stdin = PIPE". 
 
def start_command
Returns a Popen object with the command created by make_command. 
 
def error
Display an error message using g.message -e 
 
def del_temp_region
Unsets WIND_OVERRIDE and removes any region named by it. 
 
def message
Display a message using g.message 
 
def split
Platform spefic shlex.split. 
 
def fatal
Display an error message using g.message -e, then abort. 
 
def basename
various utilities, not specific to GRASS 
 
def percent
Display a progress info message using g.message -p 
 
def tempdir
Returns the name of a temporary dir, created with g.tempfile. 
 
def parse_key_val
Parse a string into a dictionary, where entries are separated by newlines and the key and value are s...
 
def region
Returns the output from running "g.region -gu", as a dictionary. 
 
def mapsets
List available mapsets. 
 
def pipe_command
Passes all arguments to start_command(), but also adds "stdout = PIPE". 
 
def try_remove
Attempt to remove a file; no exception is generated if the attempt fails. 
 
def set_raise_on_error
Define behaviour on error (error() called) 
 
def debug
Display a debugging message using g.message -d 
 
def write_command
Passes all arguments to feed_command, with the string specified by the 'stdin' argument fed to the pr...
 
def warning
Display a warning message using g.message -w 
 
def run_command
Passes all arguments to start_command(), then waits for the process to complete, returning its exit c...
 
def read_command
Passes all arguments to pipe_command, then waits for the process to complete, returning its stdout (i...
 
def region_env
Returns region settings as a string which can used as GRASS_REGION environmental variable. 
 
def tempfile
Returns the name of a temporary file, created with g.tempfile. 
 
def parser
Interface to g.parser, intended to be run from the top-level, e.g. 
 
def gisenv
Returns the output from running g.gisenv (with no arguments), as a dictionary. 
 
def find_file
Returns the output from running g.findfile as a dictionary. 
 
def verbose
Display a verbose message using g.message -v 
 
def list_pairs
List of elements as tuples.