[GRASS-SVN] r54569 - in grass/trunk/lib/python: . script

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Jan 8 01:34:43 PST 2013


Author: martinl
Date: 2013-01-08 01:34:42 -0800 (Tue, 08 Jan 2013)
New Revision: 54569

Added:
   grass/trunk/lib/python/__init__.py
   grass/trunk/lib/python/script/
   grass/trunk/lib/python/script/Makefile
   grass/trunk/lib/python/script/__init__.py
   grass/trunk/lib/python/script/array.py
   grass/trunk/lib/python/script/core.py
   grass/trunk/lib/python/script/db.py
   grass/trunk/lib/python/script/raster.py
   grass/trunk/lib/python/script/raster3d.py
   grass/trunk/lib/python/script/setup.py.sed
   grass/trunk/lib/python/script/task.py
   grass/trunk/lib/python/script/vector.py
Removed:
   grass/trunk/lib/python/__init__.py
   grass/trunk/lib/python/array.py
   grass/trunk/lib/python/core.py
   grass/trunk/lib/python/db.py
   grass/trunk/lib/python/grass__init__.py
   grass/trunk/lib/python/raster.py
   grass/trunk/lib/python/raster3d.py
   grass/trunk/lib/python/setup.py.sed
   grass/trunk/lib/python/task.py
   grass/trunk/lib/python/vector.py
Modified:
   grass/trunk/lib/python/
   grass/trunk/lib/python/Makefile
Log:
pythonlib: update layout



Property changes on: grass/trunk/lib/python
___________________________________________________________________
Modified: svn:ignore
   - OBJ.*
setup.py

   + 


Modified: grass/trunk/lib/python/Makefile
===================================================================
--- grass/trunk/lib/python/Makefile	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/Makefile	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,48 +1,26 @@
 MODULE_TOPDIR = ../..
 
-include $(MODULE_TOPDIR)/include/Make/Other.make
+#include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Dir.make
 include $(MODULE_TOPDIR)/include/Make/Python.make
 include $(MODULE_TOPDIR)/include/Make/Doxygen.make
 
-PYDIR = $(ETC)/python
-GDIR = $(PYDIR)/grass
-DSTDIR = $(GDIR)/script
+PYDIR = $(ETC)/python/grass
 
-MODULES = core db raster raster3d vector array setup task 
+SUBDIRS = script ctypes temporal pygrass
 
-PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
-PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+default: $(PYDIR)/__init__.py
+	$(MAKE) subdirs
+#	-$(MAKE) -C script || echo $(CURDIR)/script >> $(ERRORLOG)
+#	-$(MAKE) -C ctypes || echo $(CURDIR)/ctypes >> $(ERRORLOG)
+#	-$(MAKE) -C temporal || echo $(CURDIR)/temporal >> $(ERRORLOG)
+#	-$(MAKE) -C pygrass || echo $(CURDIR)/pygrass >> $(ERRORLOG)
 
-CLEAN_SUBDIRS = ctypes temporal pygrass
-EXTRA_CLEAN_FILES = setup.py
-
-default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
-	-$(MAKE) -C ctypes || echo $(CURDIR)/ctypes >> $(ERRORLOG)
-	-$(MAKE) -C temporal || echo $(CURDIR)/temporal >> $(ERRORLOG)
-	-$(MAKE) -C pygrass || echo $(CURDIR)/pygrass >> $(ERRORLOG)
-
 $(PYDIR):
 	$(MKDIR) $@
 
-$(GDIR): | $(PYDIR)
-	$(MKDIR) $@
-
-$(DSTDIR): | $(GDIR)
-	$(MKDIR) $@
-
-$(GDIR)/__init__.py: grass__init__.py | $(GDIR)
+$(PYDIR)/__init__.py: __init__.py | $(PYDIR)
 	$(INSTALL_DATA) $< $@
 
-$(DSTDIR)/%: % | $(DSTDIR)
-	$(INSTALL_DATA) $< $@
-
-$(DSTDIR)/setup.py: setup.py | $(DSTDIR)
-	$(INSTALL_DATA) $< $@
-
-setup.py: setup.py.sed
-	sed \
-	-e 's#@LD_LIBRARY_PATH_VAR@#$(LD_LIBRARY_PATH_VAR)#' \
-	$< > $@
-
-#doxygen:
+# doxygen
 DOXNAME = python

Deleted: grass/trunk/lib/python/__init__.py
===================================================================
--- grass/trunk/lib/python/__init__.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/__init__.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,5 +0,0 @@
-from core   import *
-from db     import *
-from raster import *
-from raster3d import *
-from vector import *

Copied: grass/trunk/lib/python/__init__.py (from rev 54568, grass/trunk/lib/python/grass__init__.py)
===================================================================
--- grass/trunk/lib/python/__init__.py	                        (rev 0)
+++ grass/trunk/lib/python/__init__.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,4 @@
+import os
+__all__ = ["script", "temporal"]
+if os.path.exists(os.path.join(os.path.dirname(__file__), "lib", "__init__.py")):
+    __all__.append("lib")

Deleted: grass/trunk/lib/python/array.py
===================================================================
--- grass/trunk/lib/python/array.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/array.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,356 +0,0 @@
-"""!@package grass.script.array
-
- at brief GRASS Python scripting module (2D and 3D raster with numpy)
-
-Functions to use GRASS 2D and 3D rasters with NumPy.
-
-Usage:
-
- at code
-
->>> import grass.script as grass
->>> from grass.script import array as garray
->>> 
->>> # We create a temporary region that is only valid in this python session
-... grass.use_temp_region()
->>> grass.run_command("g.region", n=80, e=120, t=60, s=0, w=0, b=0, res=20, res3=20)
-0
->>> 
->>> # Lets create a raster map numpy array
-... # based at the current region settings
-... map2d_1 = garray.array()
->>> 
->>> # Write some data
-... for y in range(map2d_1.shape[0]):
-...     for x in range(map2d_1.shape[1]):
-...         map2d_1[y][x] = y + x
-... 
->>> # Lets have a look at the array
-... print map2d_1
-[[ 0.  1.  2.  3.  4.  5.]
- [ 1.  2.  3.  4.  5.  6.]
- [ 2.  3.  4.  5.  6.  7.]
- [ 3.  4.  5.  6.  7.  8.]]
->>> # This will write the numpy array as GRASS raster map
-... # with name map2d_1
-... map2d_1.write(mapname="map2d_1", overwrite=True)
- 100%
-0
->>> 
->>> # We create a new array and read map2d_1 to modify it
-... map2d_2 = garray.array()
->>> # Don't do map2d_2 = map2d_1 % 3
-... # because: this will overwrite the internal temporary filename
-... map2d_2.read("map2d_1")
-0
->>> map2d_2 %= 3
->>> # Show the result
-... print map2d_2
-[[ 0.  1.  2.  0.  1.  2.]
- [ 1.  2.  0.  1.  2.  0.]
- [ 2.  0.  1.  2.  0.  1.]
- [ 0.  1.  2.  0.  1.  2.]]
->>> # Write the result as new raster map with name map2d_2
-... map2d_2.write(mapname="map2d_2", overwrite=True)
- 100%
-0
->>> 
->>> # Here we create a 3D raster map numpy array
-... # based in the current region settings
-... map3d_1 = garray.array3d()
->>> 
->>> # Write some data
-... # Note: the 3D array has map[depth][row][column] order
-... for z in range(map3d_1.shape[0]):
-...     for y in range(map3d_1.shape[1]):
-...         for x in range(map3d_1.shape[2]):
-...             map3d_1[z][y][x] = z + y + x
-... 
->>> # Lets have a look at the 3D array
-... print map3d_1
-[[[  0.   1.   2.   3.   4.   5.]
-  [  1.   2.   3.   4.   5.   6.]
-  [  2.   3.   4.   5.   6.   7.]
-  [  3.   4.   5.   6.   7.   8.]]
-
- [[  1.   2.   3.   4.   5.   6.]
-  [  2.   3.   4.   5.   6.   7.]
-  [  3.   4.   5.   6.   7.   8.]
-  [  4.   5.   6.   7.   8.   9.]]
-
- [[  2.   3.   4.   5.   6.   7.]
-  [  3.   4.   5.   6.   7.   8.]
-  [  4.   5.   6.   7.   8.   9.]
-  [  5.   6.   7.   8.   9.  10.]]]
->>> # This will write the numpy array as GRASS 3D raster map
-... # with name map3d_1
-... map3d_1.write(mapname="map3d_1", overwrite=True)
-Loading floating point data with 8 bytes ... (6x4x3)
- 100%
-0
->>> # We create a new 3D array and read map3d_1 to modify it
-... map3d_2 = garray.array3d()
->>> # Don't do map3d_2 = map3d_1 % 3
-... # because: this will overwrite the internal temporary filename
-... map3d_2.read("map3d_1")
-0
->>> map3d_2 %= 3
->>> # Show the result
-... print map3d_2
-[[[ 0.  1.  2.  0.  1.  2.]
-  [ 1.  2.  0.  1.  2.  0.]
-  [ 2.  0.  1.  2.  0.  1.]
-  [ 0.  1.  2.  0.  1.  2.]]
-
- [[ 1.  2.  0.  1.  2.  0.]
-  [ 2.  0.  1.  2.  0.  1.]
-  [ 0.  1.  2.  0.  1.  2.]
-  [ 1.  2.  0.  1.  2.  0.]]
-
- [[ 2.  0.  1.  2.  0.  1.]
-  [ 0.  1.  2.  0.  1.  2.]
-  [ 1.  2.  0.  1.  2.  0.]
-  [ 2.  0.  1.  2.  0.  1.]]]
->>> # Write the result as new 3D raster map with name map3d_2
-... map3d_2.write(mapname="map3d_2", overwrite=True)
-Loading floating point data with 8 bytes ... (6x4x3)
- 100%
-0
-
- at endcode
-
-(C) 2010-2012 by Glynn Clements and the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Glynn Clements
-"""
-
-import os
-import numpy
-
-import core as grass
-
-###############################################################################
-
-class array(numpy.memmap):
-    def __new__(cls, dtype=numpy.double):
-        """!Define new numpy array
-
-        @param cls
-        @param dtype data type (default: numpy.double)
-        """
-        reg = grass.region()
-        r = reg['rows']
-        c = reg['cols']
-        shape = (r, c)
-
-        filename = grass.tempfile()
-
-        self = numpy.memmap.__new__(
-            cls,
-            filename=filename,
-            dtype=dtype,
-            mode='w+',
-            shape=shape)
-
-        self.filename = filename
-        return self
-
-    def _close(self):
-        numpy.memmap._close(self)
-        if isinstance(self, array):
-            grass.try_remove(self.filename)
-
-    def read(self, mapname, null=None):
-        """!Read raster map into array
-
-        @param mapname name of raster map to be read
-        @param null null value
-
-        @return 0 on success
-        @return non-zero code on failure
-        """
-        kind = self.dtype.kind
-        size = self.dtype.itemsize
-
-        if kind == 'f':
-            flags = 'f'
-        elif kind in 'biu':
-            flags = 'i'
-        else:
-            raise ValueError(_('Invalid kind <%s>') % kind)
-
-        if size not in [1, 2, 4, 8]:
-            raise ValueError(_('Invalid size <%d>') % size)
-
-        return grass.run_command(
-            'r.out.bin',
-            flags=flags,
-            input=mapname,
-            output=self.filename,
-            bytes=size,
-            null=null,
-            quiet=True,
-            overwrite=True)
-
-    def write(self, mapname, title=None, null=None, overwrite=None):
-        """!Write array into raster map
-
-        @param mapname name for raster map
-        @param title title for raster map
-        @param null null value
-        @param overwrite True for overwritting existing raster maps
-
-        @return 0 on success
-        @return non-zero code on failure
-        """
-        kind = self.dtype.kind
-        size = self.dtype.itemsize
-
-        if kind == 'f':
-            if size == 4:
-                flags = 'f'
-            elif size == 8:
-                flags = 'd'
-            else:
-                raise ValueError(_('Invalid FP size <%d>') % size)
-            size = None
-        elif kind in 'biu':
-            if size not in [1, 2, 4]:
-                raise ValueError(_('Invalid integer size <%d>') % size)
-            flags = None
-        else:
-            raise ValueError(_('Invalid kind <%s>') % kind)
-
-        reg = grass.region()
-
-        return grass.run_command(
-            'r.in.bin',
-            flags=flags,
-            input=self.filename,
-            output=mapname,
-            title=title,
-            bytes=size,
-            anull=null,
-            overwrite=overwrite,
-            verbose=True,
-            north=reg['n'],
-            south=reg['s'],
-            east=reg['e'],
-            west=reg['w'],
-            rows=reg['rows'],
-            cols=reg['cols'])
-
-###############################################################################
-
-class array3d(numpy.memmap):
-    def __new__(cls, dtype=numpy.double):
-        """!Define new 3d numpy array
-
-        @param cls
-        @param dtype data type (default: numpy.double)
-        """
-        reg = grass.region(True)
-        r = reg['rows3']
-        c = reg['cols3']
-        d = reg['depths']
-        shape = (d, r, c)
-
-        filename = grass.tempfile()
-
-        self = numpy.memmap.__new__(
-            cls,
-            filename=filename,
-            dtype=dtype,
-            mode='w+',
-            shape=shape)
-
-        self.filename = filename
-
-        return self
-
-    def _close(self):
-
-        numpy.memmap._close(self)
-        if isinstance(self, array):
-            grass.try_remove(self.filename)
-
-    def read(self, mapname, null=None):
-        """!Read 3D raster map into array
-
-        @param mapname name of 3D raster map to be read
-        @param null null value
-
-        @return 0 on success
-        @return non-zero code on failure
-        """
-        kind = self.dtype.kind
-        size = self.dtype.itemsize
-
-        if kind == 'f':
-            flags = None # default is double
-        elif kind in 'biu':
-            flags = 'i'
-        else:
-            raise ValueError(_('Invalid kind <%s>') % kind)
-
-        if size not in [1, 2, 4, 8]:
-            raise ValueError(_('Invalid size <%d>') % size)
-
-        return grass.run_command(
-            'r3.out.bin',
-            flags=flags,
-            input=mapname,
-            output=self.filename,
-            bytes=size,
-            null=null,
-            quiet=True,
-            overwrite=True)
-
-    def write(self, mapname, null=None, overwrite=None):
-        """!Write array into 3D raster map
-
-        @param mapname name for 3D raster map
-        @param null null value
-        @param overwrite True for overwriting existing raster maps
-
-        @return 0 on success
-        @return non-zero code on failure
-        """
-        kind = self.dtype.kind
-        size = self.dtype.itemsize
-        flags = None
-
-        if kind == 'f':
-            if size != 4 and size != 8:
-                raise ValueError(_('Invalid FP size <%d>') % size)
-        elif kind in 'biu':
-            if size not in [1, 2, 4, 8]:
-                raise ValueError(_('Invalid integer size <%d>') % size)
-            flags = 'i'
-        else:
-            raise ValueError(_('Invalid kind <%s>') % kind)
-
-        reg = grass.region(True)
-
-        return grass.run_command(
-            'r3.in.bin',
-            flags=flags,
-            input=self.filename,
-            output=mapname,
-            bytes=size,
-            null=null,
-            overwrite=overwrite,
-            verbose=True,
-            north=reg['n'],
-            south=reg['s'],
-            top=reg['t'],
-            bottom=reg['b'],
-            east=reg['e'],
-            west=reg['w'],
-            depths=reg['depths'],
-            rows=reg['rows3'],
-            cols=reg['cols3'])
-

Deleted: grass/trunk/lib/python/core.py
===================================================================
--- grass/trunk/lib/python/core.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/core.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,1391 +0,0 @@
-"""!@package grass.script.core
-
- at brief GRASS Python scripting module (core functions)
-
-Core functions to be used in Python scripts.
-
-Usage:
-
- at code
-from grass.script import core as grass
-
-grass.parser()
-...
- at endcode
-
-(C) 2008-2011 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Glynn Clements
- at author Martin Landa <landa.martin gmail.com>
- at author Michael Barton <michael.barton asu.edu>
-"""
-
-import os
-import sys
-import types
-import re
-import atexit
-import subprocess
-import shutil
-import locale
-import codecs
-
-# i18N
-import gettext
-gettext.install('grasslibs', os.path.join(os.getenv("GISBASE"), 'locale'))
-
-# subprocess wrapper that uses shell on Windows
-
-class Popen(subprocess.Popen):
-    def __init__(self, args, bufsize = 0, executable = None,
-                 stdin = None, stdout = None, stderr = None,
-                 preexec_fn = None, close_fds = False, shell = None,
-                 cwd = None, env = None, universal_newlines = False,
-                 startupinfo = None, creationflags = 0):
-
-	if shell == None:
-	    shell = (sys.platform == "win32")
-
-	subprocess.Popen.__init__(self, args, bufsize, executable,
-                                  stdin, stdout, stderr,
-                                  preexec_fn, close_fds, shell,
-                                  cwd, env, universal_newlines,
-                                  startupinfo, creationflags)
-
-PIPE = subprocess.PIPE
-STDOUT = subprocess.STDOUT
-
-class ScriptError(Exception):
-    def __init__(self, msg):
-        self.value = msg
-
-    def __str__(self):
-        return self.value
-
-raise_on_error = False # raise exception instead of calling fatal()
-
-def call(*args, **kwargs):
-    return Popen(*args, **kwargs).wait()
-
-# GRASS-oriented interface to subprocess module
-
-_popen_args = ["bufsize", "executable", "stdin", "stdout", "stderr",
-	       "preexec_fn", "close_fds", "cwd", "env",
-	       "universal_newlines", "startupinfo", "creationflags"]
-
-def decode(string):
-    enc = locale.getdefaultlocale()[1]
-    if enc:
-        return string.decode(enc)
-
-    return string
-
-def _make_val(val):
-    if isinstance(val, types.StringType) or \
-            isinstance(val, types.UnicodeType):
-	return val
-    if isinstance(val, types.ListType):
-	return ",".join(map(_make_val, val))
-    if isinstance(val, types.TupleType):
-	return _make_val(list(val))
-    return str(val)
-
-def get_commands():
-    """!Create list of available GRASS commands to use when parsing
-    string from the command line
-
-    @return list of commands (set) and directory of scripts (collected
-    by extension - MS Windows only)
-
-    @code
-    >>> cmds = list(get_commands()[0])
-    >>> cmds.sort()
-    >>> cmds[:5]
-    ['d.barscale', 'd.colorlist', 'd.colortable', 'd.erase', 'd.font']
-
-    @endcode
-    """
-    gisbase = os.environ['GISBASE']
-    cmd = list()
-    scripts = {'.py': list()} if sys.platform == 'win32' else {}
-
-    def scan(gisbase, directory):
-        dir_path = os.path.join(gisbase, directory)
-        if os.path.exists(dir_path):
-            for fname in os.listdir(os.path.join(gisbase, directory)):
-                if scripts:  # win32
-                    name, ext = os.path.splitext(fname)
-                    if ext != '.manifest':
-                        cmd.append(name)
-                    if ext in scripts.keys():
-                        scripts[ext].append(name)
-                else:
-                    cmd.append(fname)
-
-    for directory in ('bin', 'scripts'):
-        scan(gisbase, directory)
-
-    # scan gui/scripts/
-    gui_path = os.path.join(gisbase, 'etc', 'gui', 'scripts')
-    if os.path.exists(gui_path):
-        os.environ["PATH"] = os.getenv("PATH") + os.pathsep + gui_path
-        cmd = cmd + os.listdir(gui_path)
-
-    return set(cmd), scripts
-
-
-def make_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **options):
-    """!Return a list of strings suitable for use as the args parameter to
-    Popen() or call(). Example:
-
-    @code
-    >>> grass.make_command("g.message", flags = 'w', message = 'this is a warning')
-    ['g.message', '-w', 'message=this is a warning']
-    @endcode
-
-    @param prog GRASS module
-    @param flags flags to be used (given as a string)
-    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
-    @param quiet True to run quietly (<tt>--q</tt>)
-    @param verbose True to run verbosely (<tt>--v</tt>)
-    @param options module's parameters
-
-    @return list of arguments
-    """
-    args = [prog]
-    if overwrite:
-	args.append("--o")
-    if quiet:
-	args.append("--q")
-    if verbose:
-	args.append("--v")
-    if flags:
-        if '-' in flags:
-            raise ScriptError("'-' is not a valid flag")
-	args.append("-%s" % flags)
-    for opt, val in options.iteritems():
-	if val != None:
-	    if opt[0] == '_':
-		opt = opt[1:]
-	    args.append("%s=%s" % (opt, _make_val(val)))
-    return args
-
-def start_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **kwargs):
-    """!Returns a Popen object with the command created by make_command.
-    Accepts any of the arguments which Popen() accepts apart from "args"
-    and "shell".
-
-    \code
-    >>> p = grass.start_command("g.gisenv", stdout = subprocess.PIPE)
-    >>> print p
-    <subprocess.Popen object at 0xb7c12f6c>
-    >>> print p.communicate()[0]
-    GISDBASE='/opt/grass-data';
-    LOCATION_NAME='spearfish60';
-    MAPSET='glynn';
-    GRASS_DB_ENCODING='ascii';
-    GUI='text';
-    MONITOR='x0';
-    \endcode
-
-    @param prog GRASS module
-    @param flags flags to be used (given as a string)
-    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
-    @param quiet True to run quietly (<tt>--q</tt>)
-    @param verbose True to run verbosely (<tt>--v</tt>)
-    @param kwargs module's parameters
-
-    @return Popen object
-    """
-    options = {}
-    popts = {}
-    for opt, val in kwargs.iteritems():
-	if opt in _popen_args:
-	    popts[opt] = val
-	else:
-	    options[opt] = val
-
-    args = make_command(prog, flags, overwrite, quiet, verbose, **options)
-
-    if debug_level() > 0:
-        sys.stderr.write("D1/%d: %s.start_command(): %s\n" % (debug_level(), __name__, ' '.join(args)))
-        sys.stderr.flush()
-
-    return Popen(args, **popts)
-
-def run_command(*args, **kwargs):
-    """!Passes all arguments to start_command(), then waits for the process to
-    complete, returning its exit code. Similar to subprocess.call(), but
-    with the make_command() interface.
-
-    @param args list of unnamed arguments (see start_command() for details)
-    @param kwargs list of named arguments (see start_command() for details)
-
-    @return exit code (0 for success)
-    """
-    ps = start_command(*args, **kwargs)
-    return ps.wait()
-
-def pipe_command(*args, **kwargs):
-    """!Passes all arguments to start_command(), but also adds
-    "stdout = PIPE". Returns the Popen object.
-
-    \code
-    >>> p = grass.pipe_command("g.gisenv")
-    >>> print p
-    <subprocess.Popen object at 0xb7c12f6c>
-    >>> print p.communicate()[0]
-    GISDBASE='/opt/grass-data';
-    LOCATION_NAME='spearfish60';
-    MAPSET='glynn';
-    GRASS_DB_ENCODING='ascii';
-    GUI='text';
-    MONITOR='x0';
-    \endcode
-
-    @param args list of unnamed arguments (see start_command() for details)
-    @param kwargs list of named arguments (see start_command() for details)
-
-    @return Popen object
-    """
-    kwargs['stdout'] = PIPE
-    return start_command(*args, **kwargs)
-
-def feed_command(*args, **kwargs):
-    """!Passes all arguments to start_command(), but also adds
-    "stdin = PIPE". Returns the Popen object.
-
-    @param args list of unnamed arguments (see start_command() for details)
-    @param kwargs list of named arguments (see start_command() for details)
-
-    @return Popen object
-    """
-    kwargs['stdin'] = PIPE
-    return start_command(*args, **kwargs)
-
-def read_command(*args, **kwargs):
-    """!Passes all arguments to pipe_command, then waits for the process to
-    complete, returning its stdout (i.e. similar to shell `backticks`).
-
-    @param args list of unnamed arguments (see start_command() for details)
-    @param kwargs list of named arguments (see start_command() for details)
-
-    @return stdout
-    """
-    ps = pipe_command(*args, **kwargs)
-    return ps.communicate()[0]
-
-def parse_command(*args, **kwargs):
-    """!Passes all arguments to read_command, then parses the output
-    by parse_key_val().
-
-    Parsing function can be optionally given by <em>parse</em> parameter
-    including its arguments, e.g.
-
-    @code
-    parse_command(..., parse = (grass.parse_key_val, { 'sep' : ':' }))
-    @endcode
-
-    or you can simply define <em>delimiter</em>
-
-    @code
-    parse_command(..., delimiter = ':')
-    @endcode
-
-    @param args list of unnamed arguments (see start_command() for details)
-    @param kwargs list of named arguments (see start_command() for details)
-
-    @return parsed module output
-    """
-    parse = None
-    parse_args = {}
-    if 'parse' in kwargs:
-        if type(kwargs['parse']) is types.TupleType:
-            parse = kwargs['parse'][0]
-            parse_args = kwargs['parse'][1]
-        del kwargs['parse']
-
-    if 'delimiter' in kwargs:
-        parse_args = { 'sep' : kwargs['delimiter'] }
-        del kwargs['delimiter']
-
-    if not parse:
-        parse = parse_key_val # use default fn
-
-    res = read_command(*args, **kwargs)
-
-    return parse(res, **parse_args)
-
-def write_command(*args, **kwargs):
-    """!Passes all arguments to feed_command, with the string specified
-    by the 'stdin' argument fed to the process' stdin.
-
-    @param args list of unnamed arguments (see start_command() for details)
-    @param kwargs list of named arguments (see start_command() for details)
-
-    @return return code
-    """
-    stdin = kwargs['stdin']
-    p = feed_command(*args, **kwargs)
-    p.stdin.write(stdin)
-    p.stdin.close()
-    return p.wait()
-
-def exec_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, env = None, **kwargs):
-    """!Interface to os.execvpe(), but with the make_command() interface.
-
-    @param prog GRASS module
-    @param flags flags to be used (given as a string)
-    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
-    @param quiet True to run quietly (<tt>--q</tt>)
-    @param verbose True to run verbosely (<tt>--v</tt>)
-    @param env directory with environmental variables
-    @param kwargs module's parameters
-
-    """
-    args = make_command(prog, flags, overwrite, quiet, verbose, **kwargs)
-    if env == None:
-	env = os.environ
-    os.execvpe(prog, args, env)
-
-# interface to g.message
-
-def message(msg, flag = None):
-    """!Display a message using `g.message`
-
-    @param msg message to be displayed
-    @param flag flags (given as string)
-    """
-    run_command("g.message", flags = flag, message = msg)
-
-def debug(msg, debug = 1):
-    """!Display a debugging message using `g.message -d`
-
-    @param msg debugging message to be displayed
-    @param debug debug level (0-5)
-    """
-    run_command("g.message", flags = 'd', message = msg, debug = debug)
-
-def verbose(msg):
-    """!Display a verbose message using `g.message -v`
-
-    @param msg verbose message to be displayed
-    """
-    message(msg, flag = 'v')
-
-def info(msg):
-    """!Display an informational message using `g.message -i`
-
-    @param msg informational message to be displayed
-    """
-    message(msg, flag = 'i')
-
-def percent(i, n, s):
-    """!Display a progress info message using `g.message -p`
-
-    @code
-    message(_("Percent complete..."))
-    n = 100
-    for i in range(n):
-        percent(i, n, 1)
-    percent(1, 1, 1)
-    @endcode
-
-    @param i current item
-    @param n total number of items
-    @param s increment size
-    """
-    message("%d %d %d" % (i, n, s), flag = 'p')
-
-def warning(msg):
-    """!Display a warning message using `g.message -w`
-
-    @param msg warning message to be displayed
-    """
-    message(msg, flag = 'w')
-
-def error(msg):
-    """!Display an error message using `g.message -e`
-
-    @param msg error message to be displayed
-    """
-    message(msg, flag = 'e')
-
-def fatal(msg):
-    """!Display an error message using `g.message -e`, then abort
-
-    Raise exception when raise_on_error is 'True'.
-
-    @param msg error message to be displayed
-    """
-    global raise_on_error
-    if raise_on_error:
-        raise ScriptError(msg)
-
-    error(msg)
-    sys.exit(1)
-
-def set_raise_on_error(raise_exp = True):
-    """!Define behaviour on fatal error (fatal() called)
-
-    @param raise_exp True to raise ScriptError instead of calling
-    sys.exit(1) in fatal()
-
-    @return current status
-    """
-    global raise_on_error
-    tmp_raise = raise_on_error
-    raise_on_error = raise_exp
-    return tmp_raise
-
-# interface to g.parser
-
-def _parse_opts(lines):
-    options = {}
-    flags = {}
-    for line in lines:
-	line = line.rstrip('\r\n')
-	if not line:
-	    break
-	try:
-	    [var, val] = line.split('=', 1)
-	except:
-	    raise SyntaxError("invalid output from g.parser: %s" % line)
-
-	if var.startswith('flag_'):
-	    flags[var[5:]] = bool(int(val))
-	elif var.startswith('opt_'):
-	    options[var[4:]] = val
-	elif var in ['GRASS_OVERWRITE', 'GRASS_VERBOSE']:
-	    os.environ[var] = val
-	else:
-	    raise SyntaxError("invalid output from g.parser: %s" % line)
-
-    return (options, flags)
-
-def parser():
-    """!Interface to g.parser, intended to be run from the top-level, e.g.:
-
-    @code
-	if __name__ == "__main__":
-	    options, flags = grass.parser()
-	    main()
-    @endcode
-
-    Thereafter, the global variables "options" and "flags" will be
-    dictionaries containing option/flag values, keyed by lower-case
-    option/flag names. The values in "options" are strings, those in
-    "flags" are Python booleans.
-    """
-    if not os.getenv("GISBASE"):
-        print >> sys.stderr, "You must be in GRASS GIS to run this program."
-        sys.exit(1)
-
-    cmdline = [basename(sys.argv[0])]
-    cmdline += ['"' + arg + '"' for arg in sys.argv[1:]]
-    os.environ['CMDLINE'] = ' '.join(cmdline)
-
-    argv = sys.argv[:]
-    name = argv[0]
-    if not os.path.isabs(name):
-	if os.sep in name or (os.altsep and os.altsep in name):
-	    argv[0] = os.path.abspath(name)
-	else:
-	    argv[0] = os.path.join(sys.path[0], name)
-
-    p = Popen(['g.parser', '-s'] + argv, stdout = PIPE)
-    s = p.communicate()[0]
-    lines = s.splitlines()
-
-    if not lines or lines[0].rstrip('\r\n') != "@ARGS_PARSED@":
-        sys.stdout.write(s)
-        sys.exit(p.returncode)
-
-    return _parse_opts(lines[1:])
-
-# interface to g.tempfile
-
-def tempfile(create = True):
-    """!Returns the name of a temporary file, created with
-    g.tempfile.
-
-    @param create True to create a file
-
-    @return path to a tmp file
-    """
-    flags = ''
-    if not create:
-        flags += 'd'
-
-    return read_command("g.tempfile", flags = flags, pid = os.getpid()).strip()
-
-def tempdir():
-    """!Returns the name of a temporary dir, created with g.tempfile."""
-    tmp = tempfile(create = False)
-    os.mkdir(tmp)
-
-    return tmp
-
-class KeyValue(dict):
-    """A general-purpose key-value store.
-
-    KeyValue is a subclass of dict, but also allows entries to be read and
-    written using attribute syntax. Example:
-
-    \code
-    >>> region = grass.region()
-    >>> region['rows']
-    477
-    >>> region.rows
-    477
-    \endcode
-    """
-
-    def __getattr__(self, key):
-        return self[key]
-
-    def __setattr__(self, key, value):
-        self[key] = value
-
-# key-value parsers
-
-def parse_key_val(s, sep = '=', dflt = None, val_type = None, vsep = None):
-    """!Parse a string into a dictionary, where entries are separated
-    by newlines and the key and value are separated by `sep' (default: `=')
-
-    @param s string to be parsed
-    @param sep key/value separator
-    @param dflt default value to be used
-    @param val_type value type (None for no cast)
-    @param vsep vertical separator (default os.linesep)
-
-    @return parsed input (dictionary of keys/values)
-    """
-    result = KeyValue()
-
-    if not s:
-        return result
-
-    if vsep:
-        lines = s.split(vsep)
-        try:
-            lines.remove('\n')
-        except ValueError:
-            pass
-    else:
-        lines = s.splitlines()
-
-    for line in lines:
-	kv = line.split(sep, 1)
-	k = kv[0].strip()
-	if len(kv) > 1:
-	    v = kv[1].strip()
-	else:
-	    v = dflt
-
-        if val_type:
-            result[k] = val_type(v)
-        else:
-            result[k] = v
-
-    return result
-
-def _text_to_key_value_dict(filename, sep=":", val_sep=","):
-    """
-        !Convert a key-value text file, where entries are separated
-        by newlines and the key and value are separated by `sep',
-        into a key-value dictionary and discover/use the correct
-        data types (float, int or string) for values.
-
-        @param filename The name or name and path of the text file to convert
-        @param sep The character that separates the keys and values, default is ":"
-        @param val_sep The character that separates the values of a single key, default is ","
-        @return The dictionary
-
-        A text file with this content:
-        \code
-        a: Hello
-        b: 1.0
-        c: 1,2,3,4,5
-        d : hello,8,0.1
-        \endcode
-
-        Will be represented as this dictionary:
-        \code
-        {'a': ['Hello'], 'c': [1, 2, 3, 4, 5], 'b': [1.0], 'd': ['hello', 8, 0.1]}
-        \endcode
-
-    """
-    text = open(filename, "r").readlines()
-    kvdict = KeyValue()
-
-    for line in text:
-        if line.find(sep) >= 0:
-            key, value = line.split(sep)
-            key = key.strip()
-            value = value.strip()
-        else:
-            # Jump over empty values
-            continue
-        values = value.split(val_sep)
-        value_list = []
-
-        for value in values:
-            not_float = False
-            not_int = False
-
-            # Convert values into correct types
-            # We first try integer then float
-            try:
-                value_converted = int(value)
-            except:
-                not_int = True
-            if not_int:
-                try:
-                    value_converted = float(value)
-                except:
-                    not_float = True
-
-            if not_int and not_float:
-                value_converted = value.strip()
-
-            value_list.append(value_converted)
-
-        kvdict[key] = value_list
-    return kvdict
-
-def compare_key_value_text_files(filename_a, filename_b, sep=":",
-                                 val_sep=",", precision=0.000001):
-    """
-        !Compare two key-value text files that may contain projection parameter
-
-        @param filename_a The name of the first key-value text file
-        @param filenmae_b The name of the second key-value text file
-        @param sep The character that separates the keys and values, default is ":"
-        @param val_sep The character that separates the values of a single key, default is ","
-        @param precision The precision with which the floating point values are compares
-           if abs(a - b) > precision : return False
-        @return True if full or almost identical, False if different
-
-        This method will print a warning in case keys that are present in the first file
-        are not present in the second one.
-        The comparison method tries to convert the values into there native format (float, int or string)
-        to allow correct comparison.
-
-        An example key-value text file may have this content:
-        \code
-        a: Hello
-        b: 1.0
-        c: 1,2,3,4,5
-        d : hello,8,0.1
-        \endcode
-    """
-    dict_a = _text_to_key_value_dict(filename_a, sep)
-    dict_b = _text_to_key_value_dict(filename_b, sep)
-
-    missing_keys = 0
-
-    # We compare matching keys
-    for key in dict_a.keys():
-        if dict_b.has_key(key):
-            # Floating point values must be handled separately
-            if isinstance(dict_a[key], float) and isinstance(dict_b[key], float):
-                if abs(dict_a[key] - dict_b[key]) > precision:
-                    return False
-            elif isinstance(dict_a[key], float) or isinstance(dict_b[key], float):
-                return False
-            else:
-                if dict_a[key] != dict_b[key]:
-                    return False
-        else:
-            missing_keys += 1
-    if missing_keys == len(dict_a):
-        return False
-    if missing_keys > 0:
-        warning(_("Several keys (%i out of %i) are missing "
-                  "in the target file")%(missing_keys, len(dict_a)))
-    return True
-
-# interface to g.gisenv
-
-def gisenv():
-    """!Returns the output from running g.gisenv (with no arguments), as a
-    dictionary. Example:
-
-    \code
-    >>> env = grass.gisenv()
-    >>> print env['GISDBASE']
-    /opt/grass-data
-    \endcode
-
-    @return list of GRASS variables
-    """
-    s = read_command("g.gisenv", flags='n')
-    return parse_key_val(s)
-
-# interface to g.region
-
-def locn_is_latlong():
-    """!Tests if location is lat/long. Value is obtained
-    by checking the "g.region -p" projection code.
-
-    @return True for a lat/long region, False otherwise
-    """
-    s = read_command("g.region", flags='p')
-    kv = parse_key_val(s, ':')
-    if kv['projection'].split(' ')[1] == '3':
-	return True
-    else:
-	return False
-
-def region(region3d = False, complete = False):
-    """!Returns the output from running "g.region -g", as a
-    dictionary. Example:
-
-    \param region3d True to get 3D region
-
-    \code
-    >>> region = grass.region()
-    >>> [region[key] for key in "nsew"]
-    [228500.0, 215000.0, 645000.0, 630000.0]
-    >>> (region['nsres'], region['ewres'])
-    (10.0, 10.0)
-    \endcode
-
-    @return dictionary of region values
-    """
-    flgs = 'g'
-    if region3d:
-        flgs += '3'
-    if complete:
-        flgs += 'cep'
-
-    s = read_command("g.region", flags = flgs)
-    reg = parse_key_val(s, val_type = float)
-    for k in ['rows',  'cols',  'cells',
-              'rows3', 'cols3', 'cells3', 'depths']:
-        if k not in reg:
-            continue
-	reg[k] = int(reg[k])
-
-    return reg
-
-def region_env(region3d = False,
-               **kwargs):
-    """!Returns region settings as a string which can used as
-    GRASS_REGION environmental variable.
-
-    If no 'kwargs' are given then the current region is used. Note
-    that this function doesn't modify the current region!
-
-    See also use_temp_region() for alternative method how to define
-    temporary region used for raster-based computation.
-
-    \param region3d True to get 3D region
-    \param kwargs g.region's parameters like 'rast', 'vect' or 'region'
-    \code
-    os.environ['GRASS_REGION'] = grass.region_env(region = 'detail')
-    grass.mapcalc('map = 1', overwrite = True)
-    os.environ.pop('GRASS_REGION')
-    \endcode
-
-    @return string with region values
-    @return empty string on error
-    """
-    # read proj/zone from WIND file
-    env = gisenv()
-    windfile = os.path.join (env['GISDBASE'], env['LOCATION_NAME'],
-                              env['MAPSET'], "WIND")
-    fd = open(windfile, "r")
-    grass_region = ''
-    for line in fd.readlines():
-        key, value = map(lambda x: x.strip(), line.split(":", 1))
-        if kwargs and key not in ('proj', 'zone'):
-            continue
-        if not kwargs and not region3d and \
-                key in ('top', 'bottom', 'cols3', 'rows3',
-                        'depths', 'e-w resol3', 'n-s resol3', 't-b resol'):
-            continue
-
-        grass_region += '%s: %s;' % (key, value)
-
-    if not kwargs: # return current region
-        return grass_region
-
-    # read other values from `g.region -g`
-    flgs = 'ug'
-    if region3d:
-        flgs += '3'
-
-    s = read_command('g.region', flags = flgs, **kwargs)
-    if not s:
-        return ''
-    reg = parse_key_val(s)
-
-    kwdata = [('north',     'n'),
-              ('south',     's'),
-              ('east',      'e'),
-              ('west',      'w'),
-              ('cols',      'cols'),
-              ('rows',      'rows'),
-              ('e-w resol', 'ewres'),
-              ('n-s resol', 'nsres')]
-    if region3d:
-        kwdata += [('top',        't'),
-                   ('bottom',     'b'),
-                   ('cols3',      'cols3'),
-                   ('rows3',      'rows3'),
-                   ('depths',     'depths'),
-                   ('e-w resol3', 'ewres3'),
-                   ('n-s resol3', 'nsres3'),
-                   ('t-b resol',  'tbres')]
-
-    for wkey, rkey in kwdata:
-        grass_region += '%s: %s;' % (wkey, reg[rkey])
-
-    return grass_region
-
-def use_temp_region():
-    """!Copies the current region to a temporary region with "g.region save=",
-    then sets WIND_OVERRIDE to refer to that region. Installs an atexit
-    handler to delete the temporary region upon termination.
-    """
-    name = "tmp.%s.%d" % (os.path.basename(sys.argv[0]), os.getpid())
-    run_command("g.region", save = name, overwrite = True)
-    os.environ['WIND_OVERRIDE'] = name
-    atexit.register(del_temp_region)
-
-def del_temp_region():
-    """!Unsets WIND_OVERRIDE and removes any region named by it."""
-    try:
-	name = os.environ.pop('WIND_OVERRIDE')
-	run_command("g.remove", quiet = True, region = name)
-    except:
-	pass
-
-# interface to g.findfile
-
-def find_file(name, element = 'cell', mapset = None):
-    """!Returns the output from running g.findfile as a
-    dictionary. Example:
-
-    \code
-    >>> result = grass.find_file('fields', element = 'vector')
-    >>> print result['fullname']
-    fields at PERMANENT
-    >>> print result['file']
-    /opt/grass-data/spearfish60/PERMANENT/vector/fields
-    \endcode
-
-    @param name file name
-    @param element element type (default 'cell')
-    @param mapset mapset name (default all mapsets in search path)
-
-    @return parsed output of g.findfile
-    """
-    if element == 'raster' or element == 'rast':
-        verbose(_('Element type should be "cell" and not "%s"') % element)
-        element = 'cell'
-    s = read_command("g.findfile", flags='n', element = element, file = name, mapset = mapset)
-    return parse_key_val(s)
-
-# interface to g.list
-
-def list_grouped(type, check_search_path = True):
-    """!List elements grouped by mapsets.
-
-    Returns the output from running g.list, as a dictionary where the
-    keys are mapset names and the values are lists of maps in that
-    mapset. Example:
-
-    @code
-    >>> grass.list_grouped('rast')['PERMANENT']
-    ['aspect', 'erosion1', 'quads', 'soils', 'strm.dist', ...
-    @endcode
-
-    @param type element type (rast, vect, rast3d, region, ...)
-    @param check_search_path True to add mapsets for the search path with no found elements
-
-    @return directory of mapsets/elements
-    """
-    if type == 'raster' or type == 'cell':
-        verbose(_('Element type should be "rast" and not "%s"') % element)
-        type = 'rast'
-    dashes_re = re.compile("^----+$")
-    mapset_re = re.compile("<(.*)>")
-    result = {}
-    if check_search_path:
-        for mapset in mapsets(search_path = True):
-            result[mapset] = []
-
-    mapset = None
-    for line in read_command("g.list", type = type).splitlines():
-	if line == "":
-	    continue
-	if dashes_re.match(line):
-	    continue
-	m = mapset_re.search(line)
-	if m:
-	    mapset = m.group(1)
-            if mapset not in result.keys():
-                result[mapset] = []
-	    continue
-        if mapset:
-            result[mapset].extend(line.split())
-
-    return result
-
-def _concat(xs):
-    result = []
-    for x in xs:
-	result.extend(x)
-    return result
-
-def list_pairs(type):
-    """!List of elements as tuples.
-
-    Returns the output from running g.list, as a list of (map, mapset)
-    pairs. Example:
-
-    @code
-    >>> grass.list_pairs('rast')
-    [('aspect', 'PERMANENT'), ('erosion1', 'PERMANENT'), ('quads', 'PERMANENT'), ...
-    @endcode
-
-    @param type element type (rast, vect, rast3d, region, ...)
-
-    @return list of tuples (map, mapset)
-    """
-    return _concat([[(map, mapset) for map in maps]
-		    for mapset, maps in list_grouped(type).iteritems()])
-
-def list_strings(type):
-    """!List of elements as strings.
-
-    Returns the output from running g.list, as a list of qualified
-    names. Example:
-
-    @code
-    >>> grass.list_strings('rast')
-    ['aspect at PERMANENT', 'erosion1 at PERMANENT', 'quads at PERMANENT', 'soils at PERMANENT', ...
-    @endcode
-
-    @param type element type
-
-    @return list of strings ('map@@mapset')
-    """
-    return ["%s@%s" % pair for pair in list_pairs(type)]
-
-# interface to g.mlist
-
-def mlist_strings(type, pattern = None, mapset = None, flag = ''):
-    """!List of elements as strings.
-
-    Returns the output from running g.mlist, as a list of qualified
-    names.
-
-    @param type element type (rast, vect, rast3d, region, ...)
-    @param pattern pattern string
-    @param mapset mapset name (if not given use search path)
-    @param flag pattern type: 'r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
-
-    @return list of elements
-    """
-    if type == 'raster' or type == 'cell':
-        verbose(_('Element type should be "rast" and not "%s"') % element)
-        type = 'rast'
-    result = list()
-    for line in read_command("g.mlist",
-                             quiet = True,
-                             flags = 'm' + flag,
-                             type = type,
-                             pattern = pattern,
-                             mapset = mapset).splitlines():
-        result.append(line.strip())
-
-    return result
-
-def mlist_pairs(type, pattern = None, mapset = None, flag = ''):
-    """!List of elements as pairs
-
-    Returns the output from running g.mlist, as a list of
-    (name, mapset) pairs
-
-    @param type element type (rast, vect, rast3d, region, ...)
-    @param pattern pattern string
-    @param mapset mapset name (if not given use search path)
-    @param flag pattern type: 'r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
-
-    @return list of elements
-    """
-    return [tuple(map.split('@', 1)) for map in mlist_strings(type, pattern, mapset, flag)]
-
-def mlist_grouped(type, pattern = None, check_search_path = True, flag = ''):
-    """!List of elements grouped by mapsets.
-
-    Returns the output from running g.mlist, as a dictionary where the
-    keys are mapset names and the values are lists of maps in that
-    mapset. Example:
-
-    @code
-    >>> grass.mlist_grouped('rast', pattern='r*')['PERMANENT']
-    ['railroads', 'roads', 'rstrct.areas', 'rushmore']
-    @endcode
-
-    @param type element type (rast, vect, rast3d, region, ...)
-    @param pattern pattern string
-    @param check_search_path True to add mapsets for the search path with no found elements
-    @param flag pattern type: 'r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
-
-    @return directory of mapsets/elements
-    """
-    if type == 'raster' or type == 'cell':
-        verbose(_('Element type should be "rast" and not "%s"') % element)
-        type = 'rast'
-    result = {}
-    if check_search_path:
-        for mapset in mapsets(search_path = True):
-            result[mapset] = []
-
-    mapset = None
-    for line in read_command("g.mlist", quiet = True, flags = "m" + flag,
-                             type = type, pattern = pattern).splitlines():
-        try:
-            name, mapset = line.split('@')
-        except ValueError:
-            warning(_("Invalid element '%s'") % line)
-            continue
-
-        if mapset in result:
-            result[mapset].append(name)
-        else:
-            result[mapset] = [name, ]
-
-    return result
-
-# color parsing
-
-named_colors = {
-    "white":   (1.00, 1.00, 1.00),
-    "black":   (0.00, 0.00, 0.00),
-    "red":     (1.00, 0.00, 0.00),
-    "green":   (0.00, 1.00, 0.00),
-    "blue":    (0.00, 0.00, 1.00),
-    "yellow":  (1.00, 1.00, 0.00),
-    "magenta": (1.00, 0.00, 1.00),
-    "cyan":    (0.00, 1.00, 1.00),
-    "aqua":    (0.00, 0.75, 0.75),
-    "grey":    (0.75, 0.75, 0.75),
-    "gray":    (0.75, 0.75, 0.75),
-    "orange":  (1.00, 0.50, 0.00),
-    "brown":   (0.75, 0.50, 0.25),
-    "purple":  (0.50, 0.00, 1.00),
-    "violet":  (0.50, 0.00, 1.00),
-    "indigo":  (0.00, 0.50, 1.00)}
-
-def parse_color(val, dflt = None):
-    """!Parses the string "val" as a GRASS colour, which can be either one of
-    the named colours or an R:G:B tuple e.g. 255:255:255. Returns an
-    (r,g,b) triple whose components are floating point values between 0
-    and 1. Example:
-
-    \code
-    >>> grass.parse_color("red")
-    (1.0, 0.0, 0.0)
-    >>> grass.parse_color("255:0:0")
-    (1.0, 0.0, 0.0)
-    \endcode
-
-    @param val color value
-    @param dflt default color value
-
-    @return tuple RGB
-    """
-    if val in named_colors:
-        return named_colors[val]
-
-    vals = val.split(':')
-    if len(vals) == 3:
-        return tuple(float(v) / 255 for v in vals)
-
-    return dflt
-
-# check GRASS_OVERWRITE
-
-def overwrite():
-    """!Return True if existing files may be overwritten"""
-    owstr = 'GRASS_OVERWRITE'
-    return owstr in os.environ and os.environ[owstr] != '0'
-
-# check GRASS_VERBOSE
-
-def verbosity():
-    """!Return the verbosity level selected by GRASS_VERBOSE"""
-    vbstr = os.getenv('GRASS_VERBOSE')
-    if vbstr:
-	return int(vbstr)
-    else:
-	return 2
-
-## various utilities, not specific to GRASS
-
-# basename inc. extension stripping
-
-def basename(path, ext = None):
-    """!Remove leading directory components and an optional extension
-    from the specified path
-
-    @param path path
-    @param ext extension
-    """
-    name = os.path.basename(path)
-    if not ext:
-	return name
-    fs = name.rsplit('.', 1)
-    if len(fs) > 1 and fs[1].lower() == ext:
-	name = fs[0]
-    return name
-
-# find a program (replacement for "which")
-
-def find_program(pgm, args = []):
-    """!Attempt to run a program, with optional arguments.
-
-    @param pgm program name
-    @param args list of arguments
-
-    @return False if the attempt failed due to a missing executable
-    @return True otherwise
-    """
-    nuldev = file(os.devnull, 'w+')
-    try:
-	ret = call([pgm] + args, stdin = nuldev, stdout = nuldev, stderr = nuldev)
-        if ret == 0:
-            found = True
-        else:
-            found = False
-    except:
-	found = False
-    nuldev.close()
-
-    return found
-
-# try to remove a file, without complaints
-
-def try_remove(path):
-    """!Attempt to remove a file; no exception is generated if the
-    attempt fails.
-
-    @param path path to file to remove
-    """
-    try:
-	os.remove(path)
-    except:
-	pass
-
-# try to remove a directory, without complaints
-
-def try_rmdir(path):
-    """!Attempt to remove a directory; no exception is generated if the
-    attempt fails.
-
-    @param path path to directory to remove
-    """
-    try:
-	os.rmdir(path)
-    except:
-	shutil.rmtree(path, ignore_errors = True)
-
-def float_or_dms(s):
-    """!Convert DMS to float.
-
-    @param s DMS value
-
-    @return float value
-    """
-    return sum(float(x) / 60 ** n for (n, x) in enumerate(s.split(':')))
-
-# interface to g.mapsets
-
-def mapsets(search_path = False):
-    """!List available mapsets
-
-    @param search_path True to list mapsets only in search path
-
-    @return list of mapsets
-    """
-    if search_path:
-        flags = 'p'
-    else:
-        flags = 'l'
-    mapsets = read_command('g.mapsets',
-                           flags = flags,
-                           sep = 'newline',
-                           quiet = True)
-    if not mapsets:
-        fatal(_("Unable to list mapsets"))
-
-    return mapsets.splitlines()
-
-# interface to `g.proj -c`
-
-def create_location(dbase, location,
-                    epsg = None, proj4 = None, filename = None, wkt = None,
-                    datum = None, datum_trans = None, desc = None):
-    """!Create new location
-
-    Raise ScriptError on error.
-
-    @param dbase path to GRASS database
-    @param location location name to create
-    @param epsg if given create new location based on EPSG code
-    @param proj4 if given create new location based on Proj4 definition
-    @param filename if given create new location based on georeferenced file
-    @param wkt if given create new location based on WKT definition (path to PRJ file)
-    @param datum GRASS format datum code
-    @param datum_trans datum transformation parameters (used for epsg and proj4)
-    @param desc description of the location (creates MYNAME file)
-    """
-    gisdbase = None
-    if epsg or proj4 or filename or wkt:
-        gisdbase = gisenv()['GISDBASE']
-        run_command('g.gisenv',
-                    set = 'GISDBASE=%s' % dbase)
-    if not os.path.exists(dbase):
-            os.mkdir(dbase)
-
-    kwargs = dict()
-    if datum:
-        kwargs['datum'] = datum
-    if datum_trans:
-        kwargs['datum_trans'] = datum_trans
-
-    if epsg:
-        ps = pipe_command('g.proj',
-                          quiet = True,
-                          epsg = epsg,
-                          location = location,
-                          stderr = PIPE,
-                          **kwargs)
-    elif proj4:
-        ps = pipe_command('g.proj',
-                          quiet = True,
-                          proj4 = proj4,
-                          location = location,
-                          stderr = PIPE,
-                          **kwargs)
-    elif filename:
-        ps = pipe_command('g.proj',
-                          quiet = True,
-                          georef = filename,
-                          location = location,
-                          stderr = PIPE)
-    elif wkt:
-        ps = pipe_command('g.proj',
-                          quiet = True,
-                          wkt = wkt,
-                          location = location,
-                          stderr = PIPE)
-    else:
-        _create_location_xy(dbase, location)
-
-    if epsg or proj4 or filename or wkt:
-        error = ps.communicate()[1]
-        run_command('g.gisenv',
-                    set = 'GISDBASE=%s' % gisdbase)
-
-        if ps.returncode != 0 and error:
-            raise ScriptError(repr(error))
-
-    try:
-        fd = codecs.open(os.path.join(dbase, location,
-                                      'PERMANENT', 'MYNAME'),
-                         encoding = 'utf-8', mode = 'w')
-        if desc:
-            fd.write(desc + os.linesep)
-        else:
-            fd.write(os.linesep)
-        fd.close()
-    except OSError, e:
-        raise ScriptError(repr(e))
-
-def _create_location_xy(database, location):
-    """!Create unprojected location
-
-    Raise ScriptError on error.
-
-    @param database GRASS database where to create new location
-    @param location location name
-    """
-    cur_dir = os.getcwd()
-    try:
-        os.chdir(database)
-        os.mkdir(location)
-        os.mkdir(os.path.join(location, 'PERMANENT'))
-
-        # create DEFAULT_WIND and WIND files
-        regioninfo = ['proj:       0',
-                      'zone:       0',
-                      'north:      1',
-                      'south:      0',
-                      'east:       1',
-                      'west:       0',
-                      'cols:       1',
-                      'rows:       1',
-                      'e-w resol:  1',
-                      'n-s resol:  1',
-                      'top:        1',
-                      'bottom:     0',
-                      'cols3:      1',
-                      'rows3:      1',
-                      'depths:     1',
-                      'e-w resol3: 1',
-                      'n-s resol3: 1',
-                      't-b resol:  1']
-
-        defwind = open(os.path.join(location,
-                                    "PERMANENT", "DEFAULT_WIND"), 'w')
-        for param in regioninfo:
-            defwind.write(param + '%s' % os.linesep)
-        defwind.close()
-
-        shutil.copy(os.path.join(location, "PERMANENT", "DEFAULT_WIND"),
-                    os.path.join(location, "PERMANENT", "WIND"))
-
-        os.chdir(cur_dir)
-    except OSError, e:
-        raise ScriptError(repr(e))
-
-# interface to g.version
-
-def version():
-    """!Get GRASS version as dictionary
-
-    @code
-    print version()
-
-    {'proj4': '4.8.0', 'geos': '3.3.5', 'libgis_revision': '52468',
-     'libgis_date': '2012-07-27 22:53:30 +0200 (Fri, 27 Jul 2012)',
-     'version': '7.0.svn', 'date': '2012', 'gdal': '2.0dev', 'revision': '53670'}
-    @endcode
-    """
-    data = parse_command('g.version',
-                         flags = 'rge')
-    for k, v in data.iteritems():
-        data[k.strip()] = v.replace('"', '').strip()
-
-    return data
-
-# get debug_level
-_debug_level = None
-
-def debug_level():
-    global _debug_level
-    if _debug_level is not None:
-        return _debug_level
-    _debug_level = 0
-    if find_program('g.gisenv', ['--help']):
-        _debug_level = int(gisenv().get('DEBUG', 0))

Deleted: grass/trunk/lib/python/db.py
===================================================================
--- grass/trunk/lib/python/db.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/db.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,155 +0,0 @@
-"""!@package grass.script.db
-
- at brief GRASS Python scripting module (database functions)
-
-Database related functions to be used in Python scripts.
-
-Usage:
-
- at code
-from grass.script import db as grass
-
-grass.db_describe(table)
-...
- at endcode
-
-(C) 2008-2009, 2012 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Glynn Clements
- at author Martin Landa <landa.martin gmail.com>
-"""
-
-import tempfile as pytempfile # conflict with core.tempfile
-
-from core import *
-
-def db_describe(table, **args):
-    """!Return the list of columns for a database table
-    (interface to `db.describe -c'). Example:
-
-    \code
-    >>> grass.db_describe('lakes')
-    {'nrows': 15279, 'cols': [['cat', 'INTEGER', '11'], ['AREA', 'DOUBLE PRECISION', '20'],
-    ['PERIMETER', 'DOUBLE PRECISION', '20'], ['FULL_HYDRO', 'DOUBLE PRECISION', '20'],
-    ['FULL_HYDR2', 'DOUBLE PRECISION', '20'], ['FTYPE', 'CHARACTER', '24'],
-    ['FCODE', 'INTEGER', '11'], ['NAME', 'CHARACTER', '99']], 'ncols': 8}
-    \endcode
-
-    @param table table name
-    @param args
-
-    @return parsed module output
-    """
-    s = read_command('db.describe', flags = 'c', table = table, **args)
-    if not s:
-        fatal(_("Unable to describe table <%s>") % table)
-    
-    cols = []
-    result = {}
-    for l in s.splitlines():
-        f = l.split(':')
-        key = f[0]
-        f[1] = f[1].lstrip(' ')
-        if key.startswith('Column '):
-            n = int(key.split(' ')[1])
-            cols.insert(n, f[1:])
-        elif key in ['ncols', 'nrows']:
-            result[key] = int(f[1])
-        else:
-            result[key] = f[1:]
-    result['cols'] = cols
-    
-    return result
-
-# run "db.connect -g" and parse output
-
-def db_table_exist(table, **args):
-    """!Return True if database table exists, False otherwise
-
-    @param table table name
-    @param args
-
-    @return True for success, False otherwise
-    """
-    result = run_command('db.describe', flags = 'c', table = table, **args)
-    if result == 0:
-            return True
-    else:
-            return False
-
-def db_connection():
-    """!Return the current database connection parameters
-    (interface to `db.connect -g'). Example:
-
-    \code
-    >>> grass.db_connection()
-    {'group': 'x', 'schema': '', 'driver': 'dbf', 'database': '$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/'}
-    \endcode
-
-    @return parsed output of db.connect
-    """
-    return parse_command('db.connect', flags = 'g')
-
-def db_select(sql = None, filename = None, table = None, **args):
-    """!Perform SQL select statement
-
-    Note: one of <em>sql</em>, <em>filename</em>, or <em>table</em>
-    arguments must be provided.
-    
-    Examples:
-    
-    \code
-    grass.db_select(sql = 'SELECT cat,CAMPUS FROM busstopsall WHERE cat < 4')
-
-    (('1', 'Vet School'), ('2', 'West'), ('3', 'North'))
-    \endcode
-    
-    \code
-     grass.db_select(filename = '/path/to/sql/file')
-    \endcode
-
-    Simplyfied usage 
-    
-    \code
-    grass.db_select(table = 'busstopsall')
-    \endcode
-
-    performs <tt>SELECT * FROM busstopsall</tt>.
-
-    @param sql SQL statement to perform (or None)
-    @param filename name of file with SQL statements (or None)
-    @param table name of table to query (or None)
-    @param args  see \gmod{db.select} arguments
-    """
-    fname = tempfile(create = False)
-    if sql:
-        args['sql'] = sql
-    elif filename:
-        args['input'] = filename
-    elif table:
-        args['table'] = table
-    else:
-        fatal(_("Programmer error: '%(sql)s', '%(filename)s', or '%(table)s' must be provided") %
-              {'sql': 'sql', 'filename': 'filename', 'table': 'table'} )
-    
-    if 'sep' not in args:
-        args['sep'] = '|'
-    
-    ret = run_command('db.select', quiet = True,
-                      flags = 'c',
-                      output = fname,
-                      **args)
-    
-    if ret != 0:
-        fatal(_("Fetching data failed"))
-    
-    ofile = open(fname)
-    result = map(lambda x: tuple(x.rstrip(os.linesep).split(args['sep'])),
-                 ofile.readlines())
-    ofile.close()
-    try_remove(fname)
-        
-    return tuple(result)

Deleted: grass/trunk/lib/python/grass__init__.py
===================================================================
--- grass/trunk/lib/python/grass__init__.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/grass__init__.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,4 +0,0 @@
-import os
-__all__ = ["script", "temporal"]
-if os.path.exists(os.path.join(os.path.dirname(__file__), "lib", "__init__.py")):
-    __all__.append("lib")

Deleted: grass/trunk/lib/python/raster.py
===================================================================
--- grass/trunk/lib/python/raster.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/raster.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,137 +0,0 @@
-"""!@package grass.script.raster
-
- at brief GRASS Python scripting module (raster functions)
-
-Raster related functions to be used in Python scripts.
-
-Usage:
-
- at code
-from grass.script import raster as grass
-
-grass.raster_history(map)
-...
- at endcode
-
-(C) 2008-2011 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Glynn Clements
- at author Martin Landa <landa.martin gmail.com>
-"""
-
-import os
-import string
-
-from core import *
-
-# add raster history
-
-def raster_history(map):
-    """!Set the command history for a raster map to the command used to
-    invoke the script (interface to `r.support').
-
-    @param map map name
-
-    @return True on success
-    @return False on failure
-    """
-    current_mapset = gisenv()['MAPSET']
-    if find_file(name = map)['mapset'] == current_mapset:
-        run_command('r.support', map = map, history = os.environ['CMDLINE'])
-        return True
-    
-    warning(_("Unable to write history for <%(map)s>. "
-              "Raster map <%(map)s> not found in current mapset." % { 'map' : map, 'map' : map}))
-    return False
-
-# run "r.info -gre ..." and parse output
-
-def raster_info(map):
-    """!Return information about a raster map (interface to
-    `r.info'). Example:
-
-    \code
-    >>> grass.raster_info('elevation')
-    {'north': 228500.0, 'timestamp': '"none"', 'min': 55.578792572021499,
-    'datatype': 'FCELL', 'max': 156.32986450195301, 'ewres': 10.0,
-    'vertical_datum': '', 'west': 630000.0, 'units': '',
-    'title': 'South-West Wake county: Elevation NED 10m (elev_ned10m)',
-    'east': 645000.0, 'nsres': 10.0, 'south': 215000.0}
-    \endcode
-
-    @param map map name
-    
-    @return parsed raster info
-    """
-
-    def float_or_null(s):
-        if s == 'NULL':
-            return None
-        else:
-            return float(s)
-
-    s = read_command('r.info', flags = 'gre', map = map)
-    kv = parse_key_val(s)
-    for k in ['min', 'max']:
-	kv[k] = float_or_null(kv[k])
-    for k in ['north', 'south', 'east', 'west']:
-	kv[k] = float(kv[k])
-    for k in ['nsres', 'ewres']:
-	kv[k] = float_or_dms(kv[k])
-    return kv
-
-# interface to r.mapcalc
-
-def mapcalc(exp, quiet = False, verbose = False, overwrite = False, **kwargs):
-    """!Interface to r.mapcalc.
-
-    @param exp expression
-    @param quiet True to run quietly (<tt>--q</tt>)
-    @param verbose True to run verbosely (<tt>--v</tt>)
-    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
-    @param kwargs
-    """
-    t = string.Template(exp)
-    e = t.substitute(**kwargs)
-
-    if run_command('r.mapcalc', expression = e,
-                   quiet = quiet,
-                   verbose = verbose,
-                   overwrite = overwrite) != 0:
-	fatal(_("An error occurred while running r.mapcalc"))
-
-
-def mapcalc_start(exp, quiet = False, verbose = False, overwrite = False, **kwargs):
-    """!Interface to r.mapcalc, doesn't wait for it to finish, returns Popen object.
-
-    \code
-    >>> expr1 = '"%s" = "%s" * 10' % (output, input)
-    >>> expr2 = '...'   # etc.
-    >>> # launch the jobs:
-    >>> p1 = grass.mapcalc_start(expr1)
-    >>> p2 = grass.mapcalc_start(expr2)   # etc.
-    ...
-    >>> # wait for them to finish:
-    >>> p1.wait()
-    >>> p2.wait()   # etc.
-    \endcode
-
-    @param exp expression
-    @param quiet True to run quietly (<tt>--q</tt>)
-    @param verbose True to run verbosely (<tt>--v</tt>)
-    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
-    @param kwargs
-    
-    @return Popen object
-    """
-    t = string.Template(exp)
-    e = t.substitute(**kwargs)
-
-    return start_command('r.mapcalc', expression = e,
-                        quiet = quiet,
-                        verbose = verbose,
-                        overwrite = overwrite)
-

Deleted: grass/trunk/lib/python/raster3d.py
===================================================================
--- grass/trunk/lib/python/raster3d.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/raster3d.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,89 +0,0 @@
-"""!@package grass.script.raster3d
-
- at brief GRASS Python scripting module (raster3d functions)
-
-Raster3d related functions to be used in Python scripts.
-
-Usage:
-
- at code
-from grass.script import raster3d as grass
-
-grass.raster3d_info(map)
-...
- at endcode
-
-(C) 2008-2009 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Glynn Clements
- at author Martin Landa <landa.martin gmail.com>
- at author Soeren Gebbert <soeren.gebbert gmail.com>
-"""
-
-import os
-import string
-
-from core import *
-
-# add raster history
-
-# run "r3.info -rstgip ..." and parse output
-
-def raster3d_info(map):
-    """!Return information about a raster3d map (interface to
-    `r3.info'). Example:
-
-    \code
-    >>> grass.raster3d_info('volume')
-    {'tiledimz': 1, 'tbres': 1.0, 'tiledimx': 27, 'tiledimy': 16, 'north': 60.490001999999997, 'tilenumy': 1, 'tilenumz': 1, 
-    'min': 1.0, 'datatype': '"DCELL"', 'max': 1.0, 'top': 0.5, 'bottom': -0.5, 'west': -3.2200000000000002, 'tilenumx': 1, 
-    'ewres': 0.98222219, 'east': 23.299999, 'nsres': 0.99937511999999995, 'Timestamp': '"none"', 'south': 44.5}
-    \endcode
-
-    @param map map name
-    
-    @return parsed raster3d info
-    """
-
-    def float_or_null(s):
-        if s == 'NULL':
-            return None
-        else:
-            return float(s)
-
-    s = read_command('r3.info', flags='rg', map=map)
-    kv = parse_key_val(s)
-    for k in ['min', 'max']:
-	kv[k] = float_or_null(kv[k])
-    for k in ['north', 'south', 'east', 'west', 'top', 'bottom']:
-	kv[k] = float(kv[k])
-    for k in ['nsres', 'ewres', 'tbres']:
-	kv[k] = float_or_dms(kv[k])
-    for k in ['tilenumx', 'tilenumy', 'tilenumz']:
-	kv[k] = int(kv[k])
-    for k in ['tiledimx', 'tiledimy', 'tiledimz']:
-	kv[k] = int(kv[k])
-    return kv
-
-# interface to r3.mapcalc
-
-def mapcalc3d(exp, quiet = False, verbose = False, overwrite = False, **kwargs):
-    """!Interface to r3.mapcalc.
-
-    @param exp expression
-    @param quiet True to run quietly (<tt>--q</tt>)
-    @param verbose True to run verbosely (<tt>--v</tt>)
-    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
-    @param kwargs
-    """
-    t = string.Template(exp)
-    e = t.substitute(**kwargs)
-
-    if run_command('r3.mapcalc', expression = e,
-                   quiet = quiet,
-                   verbose = verbose,
-                   overwrite = overwrite) != 0:
-	fatal(_("An error occurred while running r3.mapcalc"))


Property changes on: grass/trunk/lib/python/script
___________________________________________________________________
Added: svn:ignore
   + setup.py


Copied: grass/trunk/lib/python/script/Makefile (from rev 54568, grass/trunk/lib/python/Makefile)
===================================================================
--- grass/trunk/lib/python/script/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/script/Makefile	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,30 @@
+MODULE_TOPDIR = ../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+include $(MODULE_TOPDIR)/include/Make/Doxygen.make
+
+DSTDIR = $(ETC)/python/grass/script
+
+MODULES = core db raster raster3d vector array setup task 
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+EXTRA_CLEAN_FILES = setup.py
+
+default: $(PYFILES) $(PYCFILES)
+
+$(DSTDIR):
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+$(DSTDIR)/setup.py: setup.py | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+setup.py: setup.py.sed
+	sed \
+	-e 's#@LD_LIBRARY_PATH_VAR@#$(LD_LIBRARY_PATH_VAR)#' \
+	$< > $@

Copied: grass/trunk/lib/python/script/__init__.py (from rev 54568, grass/trunk/lib/python/__init__.py)
===================================================================
--- grass/trunk/lib/python/script/__init__.py	                        (rev 0)
+++ grass/trunk/lib/python/script/__init__.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,5 @@
+from core   import *
+from db     import *
+from raster import *
+from raster3d import *
+from vector import *

Copied: grass/trunk/lib/python/script/array.py (from rev 54568, grass/trunk/lib/python/array.py)
===================================================================
--- grass/trunk/lib/python/script/array.py	                        (rev 0)
+++ grass/trunk/lib/python/script/array.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,356 @@
+"""!@package grass.script.array
+
+ at brief GRASS Python scripting module (2D and 3D raster with numpy)
+
+Functions to use GRASS 2D and 3D rasters with NumPy.
+
+Usage:
+
+ at code
+
+>>> import grass.script as grass
+>>> from grass.script import array as garray
+>>> 
+>>> # We create a temporary region that is only valid in this python session
+... grass.use_temp_region()
+>>> grass.run_command("g.region", n=80, e=120, t=60, s=0, w=0, b=0, res=20, res3=20)
+0
+>>> 
+>>> # Lets create a raster map numpy array
+... # based at the current region settings
+... map2d_1 = garray.array()
+>>> 
+>>> # Write some data
+... for y in range(map2d_1.shape[0]):
+...     for x in range(map2d_1.shape[1]):
+...         map2d_1[y][x] = y + x
+... 
+>>> # Lets have a look at the array
+... print map2d_1
+[[ 0.  1.  2.  3.  4.  5.]
+ [ 1.  2.  3.  4.  5.  6.]
+ [ 2.  3.  4.  5.  6.  7.]
+ [ 3.  4.  5.  6.  7.  8.]]
+>>> # This will write the numpy array as GRASS raster map
+... # with name map2d_1
+... map2d_1.write(mapname="map2d_1", overwrite=True)
+ 100%
+0
+>>> 
+>>> # We create a new array and read map2d_1 to modify it
+... map2d_2 = garray.array()
+>>> # Don't do map2d_2 = map2d_1 % 3
+... # because: this will overwrite the internal temporary filename
+... map2d_2.read("map2d_1")
+0
+>>> map2d_2 %= 3
+>>> # Show the result
+... print map2d_2
+[[ 0.  1.  2.  0.  1.  2.]
+ [ 1.  2.  0.  1.  2.  0.]
+ [ 2.  0.  1.  2.  0.  1.]
+ [ 0.  1.  2.  0.  1.  2.]]
+>>> # Write the result as new raster map with name map2d_2
+... map2d_2.write(mapname="map2d_2", overwrite=True)
+ 100%
+0
+>>> 
+>>> # Here we create a 3D raster map numpy array
+... # based in the current region settings
+... map3d_1 = garray.array3d()
+>>> 
+>>> # Write some data
+... # Note: the 3D array has map[depth][row][column] order
+... for z in range(map3d_1.shape[0]):
+...     for y in range(map3d_1.shape[1]):
+...         for x in range(map3d_1.shape[2]):
+...             map3d_1[z][y][x] = z + y + x
+... 
+>>> # Lets have a look at the 3D array
+... print map3d_1
+[[[  0.   1.   2.   3.   4.   5.]
+  [  1.   2.   3.   4.   5.   6.]
+  [  2.   3.   4.   5.   6.   7.]
+  [  3.   4.   5.   6.   7.   8.]]
+
+ [[  1.   2.   3.   4.   5.   6.]
+  [  2.   3.   4.   5.   6.   7.]
+  [  3.   4.   5.   6.   7.   8.]
+  [  4.   5.   6.   7.   8.   9.]]
+
+ [[  2.   3.   4.   5.   6.   7.]
+  [  3.   4.   5.   6.   7.   8.]
+  [  4.   5.   6.   7.   8.   9.]
+  [  5.   6.   7.   8.   9.  10.]]]
+>>> # This will write the numpy array as GRASS 3D raster map
+... # with name map3d_1
+... map3d_1.write(mapname="map3d_1", overwrite=True)
+Loading floating point data with 8 bytes ... (6x4x3)
+ 100%
+0
+>>> # We create a new 3D array and read map3d_1 to modify it
+... map3d_2 = garray.array3d()
+>>> # Don't do map3d_2 = map3d_1 % 3
+... # because: this will overwrite the internal temporary filename
+... map3d_2.read("map3d_1")
+0
+>>> map3d_2 %= 3
+>>> # Show the result
+... print map3d_2
+[[[ 0.  1.  2.  0.  1.  2.]
+  [ 1.  2.  0.  1.  2.  0.]
+  [ 2.  0.  1.  2.  0.  1.]
+  [ 0.  1.  2.  0.  1.  2.]]
+
+ [[ 1.  2.  0.  1.  2.  0.]
+  [ 2.  0.  1.  2.  0.  1.]
+  [ 0.  1.  2.  0.  1.  2.]
+  [ 1.  2.  0.  1.  2.  0.]]
+
+ [[ 2.  0.  1.  2.  0.  1.]
+  [ 0.  1.  2.  0.  1.  2.]
+  [ 1.  2.  0.  1.  2.  0.]
+  [ 2.  0.  1.  2.  0.  1.]]]
+>>> # Write the result as new 3D raster map with name map3d_2
+... map3d_2.write(mapname="map3d_2", overwrite=True)
+Loading floating point data with 8 bytes ... (6x4x3)
+ 100%
+0
+
+ at endcode
+
+(C) 2010-2012 by Glynn Clements and the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Glynn Clements
+"""
+
+import os
+import numpy
+
+import core as grass
+
+###############################################################################
+
+class array(numpy.memmap):
+    def __new__(cls, dtype=numpy.double):
+        """!Define new numpy array
+
+        @param cls
+        @param dtype data type (default: numpy.double)
+        """
+        reg = grass.region()
+        r = reg['rows']
+        c = reg['cols']
+        shape = (r, c)
+
+        filename = grass.tempfile()
+
+        self = numpy.memmap.__new__(
+            cls,
+            filename=filename,
+            dtype=dtype,
+            mode='w+',
+            shape=shape)
+
+        self.filename = filename
+        return self
+
+    def _close(self):
+        numpy.memmap._close(self)
+        if isinstance(self, array):
+            grass.try_remove(self.filename)
+
+    def read(self, mapname, null=None):
+        """!Read raster map into array
+
+        @param mapname name of raster map to be read
+        @param null null value
+
+        @return 0 on success
+        @return non-zero code on failure
+        """
+        kind = self.dtype.kind
+        size = self.dtype.itemsize
+
+        if kind == 'f':
+            flags = 'f'
+        elif kind in 'biu':
+            flags = 'i'
+        else:
+            raise ValueError(_('Invalid kind <%s>') % kind)
+
+        if size not in [1, 2, 4, 8]:
+            raise ValueError(_('Invalid size <%d>') % size)
+
+        return grass.run_command(
+            'r.out.bin',
+            flags=flags,
+            input=mapname,
+            output=self.filename,
+            bytes=size,
+            null=null,
+            quiet=True,
+            overwrite=True)
+
+    def write(self, mapname, title=None, null=None, overwrite=None):
+        """!Write array into raster map
+
+        @param mapname name for raster map
+        @param title title for raster map
+        @param null null value
+        @param overwrite True for overwritting existing raster maps
+
+        @return 0 on success
+        @return non-zero code on failure
+        """
+        kind = self.dtype.kind
+        size = self.dtype.itemsize
+
+        if kind == 'f':
+            if size == 4:
+                flags = 'f'
+            elif size == 8:
+                flags = 'd'
+            else:
+                raise ValueError(_('Invalid FP size <%d>') % size)
+            size = None
+        elif kind in 'biu':
+            if size not in [1, 2, 4]:
+                raise ValueError(_('Invalid integer size <%d>') % size)
+            flags = None
+        else:
+            raise ValueError(_('Invalid kind <%s>') % kind)
+
+        reg = grass.region()
+
+        return grass.run_command(
+            'r.in.bin',
+            flags=flags,
+            input=self.filename,
+            output=mapname,
+            title=title,
+            bytes=size,
+            anull=null,
+            overwrite=overwrite,
+            verbose=True,
+            north=reg['n'],
+            south=reg['s'],
+            east=reg['e'],
+            west=reg['w'],
+            rows=reg['rows'],
+            cols=reg['cols'])
+
+###############################################################################
+
+class array3d(numpy.memmap):
+    def __new__(cls, dtype=numpy.double):
+        """!Define new 3d numpy array
+
+        @param cls
+        @param dtype data type (default: numpy.double)
+        """
+        reg = grass.region(True)
+        r = reg['rows3']
+        c = reg['cols3']
+        d = reg['depths']
+        shape = (d, r, c)
+
+        filename = grass.tempfile()
+
+        self = numpy.memmap.__new__(
+            cls,
+            filename=filename,
+            dtype=dtype,
+            mode='w+',
+            shape=shape)
+
+        self.filename = filename
+
+        return self
+
+    def _close(self):
+
+        numpy.memmap._close(self)
+        if isinstance(self, array):
+            grass.try_remove(self.filename)
+
+    def read(self, mapname, null=None):
+        """!Read 3D raster map into array
+
+        @param mapname name of 3D raster map to be read
+        @param null null value
+
+        @return 0 on success
+        @return non-zero code on failure
+        """
+        kind = self.dtype.kind
+        size = self.dtype.itemsize
+
+        if kind == 'f':
+            flags = None # default is double
+        elif kind in 'biu':
+            flags = 'i'
+        else:
+            raise ValueError(_('Invalid kind <%s>') % kind)
+
+        if size not in [1, 2, 4, 8]:
+            raise ValueError(_('Invalid size <%d>') % size)
+
+        return grass.run_command(
+            'r3.out.bin',
+            flags=flags,
+            input=mapname,
+            output=self.filename,
+            bytes=size,
+            null=null,
+            quiet=True,
+            overwrite=True)
+
+    def write(self, mapname, null=None, overwrite=None):
+        """!Write array into 3D raster map
+
+        @param mapname name for 3D raster map
+        @param null null value
+        @param overwrite True for overwriting existing raster maps
+
+        @return 0 on success
+        @return non-zero code on failure
+        """
+        kind = self.dtype.kind
+        size = self.dtype.itemsize
+        flags = None
+
+        if kind == 'f':
+            if size != 4 and size != 8:
+                raise ValueError(_('Invalid FP size <%d>') % size)
+        elif kind in 'biu':
+            if size not in [1, 2, 4, 8]:
+                raise ValueError(_('Invalid integer size <%d>') % size)
+            flags = 'i'
+        else:
+            raise ValueError(_('Invalid kind <%s>') % kind)
+
+        reg = grass.region(True)
+
+        return grass.run_command(
+            'r3.in.bin',
+            flags=flags,
+            input=self.filename,
+            output=mapname,
+            bytes=size,
+            null=null,
+            overwrite=overwrite,
+            verbose=True,
+            north=reg['n'],
+            south=reg['s'],
+            top=reg['t'],
+            bottom=reg['b'],
+            east=reg['e'],
+            west=reg['w'],
+            depths=reg['depths'],
+            rows=reg['rows3'],
+            cols=reg['cols3'])
+

Copied: grass/trunk/lib/python/script/core.py (from rev 54568, grass/trunk/lib/python/core.py)
===================================================================
--- grass/trunk/lib/python/script/core.py	                        (rev 0)
+++ grass/trunk/lib/python/script/core.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,1391 @@
+"""!@package grass.script.core
+
+ at brief GRASS Python scripting module (core functions)
+
+Core functions to be used in Python scripts.
+
+Usage:
+
+ at code
+from grass.script import core as grass
+
+grass.parser()
+...
+ at endcode
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Glynn Clements
+ at author Martin Landa <landa.martin gmail.com>
+ at author Michael Barton <michael.barton asu.edu>
+"""
+
+import os
+import sys
+import types
+import re
+import atexit
+import subprocess
+import shutil
+import locale
+import codecs
+
+# i18N
+import gettext
+gettext.install('grasslibs', os.path.join(os.getenv("GISBASE"), 'locale'))
+
+# subprocess wrapper that uses shell on Windows
+
+class Popen(subprocess.Popen):
+    def __init__(self, args, bufsize = 0, executable = None,
+                 stdin = None, stdout = None, stderr = None,
+                 preexec_fn = None, close_fds = False, shell = None,
+                 cwd = None, env = None, universal_newlines = False,
+                 startupinfo = None, creationflags = 0):
+
+	if shell == None:
+	    shell = (sys.platform == "win32")
+
+	subprocess.Popen.__init__(self, args, bufsize, executable,
+                                  stdin, stdout, stderr,
+                                  preexec_fn, close_fds, shell,
+                                  cwd, env, universal_newlines,
+                                  startupinfo, creationflags)
+
+PIPE = subprocess.PIPE
+STDOUT = subprocess.STDOUT
+
+class ScriptError(Exception):
+    def __init__(self, msg):
+        self.value = msg
+
+    def __str__(self):
+        return self.value
+
+raise_on_error = False # raise exception instead of calling fatal()
+
+def call(*args, **kwargs):
+    return Popen(*args, **kwargs).wait()
+
+# GRASS-oriented interface to subprocess module
+
+_popen_args = ["bufsize", "executable", "stdin", "stdout", "stderr",
+	       "preexec_fn", "close_fds", "cwd", "env",
+	       "universal_newlines", "startupinfo", "creationflags"]
+
+def decode(string):
+    enc = locale.getdefaultlocale()[1]
+    if enc:
+        return string.decode(enc)
+
+    return string
+
+def _make_val(val):
+    if isinstance(val, types.StringType) or \
+            isinstance(val, types.UnicodeType):
+	return val
+    if isinstance(val, types.ListType):
+	return ",".join(map(_make_val, val))
+    if isinstance(val, types.TupleType):
+	return _make_val(list(val))
+    return str(val)
+
+def get_commands():
+    """!Create list of available GRASS commands to use when parsing
+    string from the command line
+
+    @return list of commands (set) and directory of scripts (collected
+    by extension - MS Windows only)
+
+    @code
+    >>> cmds = list(get_commands()[0])
+    >>> cmds.sort()
+    >>> cmds[:5]
+    ['d.barscale', 'd.colorlist', 'd.colortable', 'd.erase', 'd.font']
+
+    @endcode
+    """
+    gisbase = os.environ['GISBASE']
+    cmd = list()
+    scripts = {'.py': list()} if sys.platform == 'win32' else {}
+
+    def scan(gisbase, directory):
+        dir_path = os.path.join(gisbase, directory)
+        if os.path.exists(dir_path):
+            for fname in os.listdir(os.path.join(gisbase, directory)):
+                if scripts:  # win32
+                    name, ext = os.path.splitext(fname)
+                    if ext != '.manifest':
+                        cmd.append(name)
+                    if ext in scripts.keys():
+                        scripts[ext].append(name)
+                else:
+                    cmd.append(fname)
+
+    for directory in ('bin', 'scripts'):
+        scan(gisbase, directory)
+
+    # scan gui/scripts/
+    gui_path = os.path.join(gisbase, 'etc', 'gui', 'scripts')
+    if os.path.exists(gui_path):
+        os.environ["PATH"] = os.getenv("PATH") + os.pathsep + gui_path
+        cmd = cmd + os.listdir(gui_path)
+
+    return set(cmd), scripts
+
+
+def make_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **options):
+    """!Return a list of strings suitable for use as the args parameter to
+    Popen() or call(). Example:
+
+    @code
+    >>> grass.make_command("g.message", flags = 'w', message = 'this is a warning')
+    ['g.message', '-w', 'message=this is a warning']
+    @endcode
+
+    @param prog GRASS module
+    @param flags flags to be used (given as a string)
+    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
+    @param quiet True to run quietly (<tt>--q</tt>)
+    @param verbose True to run verbosely (<tt>--v</tt>)
+    @param options module's parameters
+
+    @return list of arguments
+    """
+    args = [prog]
+    if overwrite:
+	args.append("--o")
+    if quiet:
+	args.append("--q")
+    if verbose:
+	args.append("--v")
+    if flags:
+        if '-' in flags:
+            raise ScriptError("'-' is not a valid flag")
+	args.append("-%s" % flags)
+    for opt, val in options.iteritems():
+	if val != None:
+	    if opt[0] == '_':
+		opt = opt[1:]
+	    args.append("%s=%s" % (opt, _make_val(val)))
+    return args
+
+def start_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **kwargs):
+    """!Returns a Popen object with the command created by make_command.
+    Accepts any of the arguments which Popen() accepts apart from "args"
+    and "shell".
+
+    \code
+    >>> p = grass.start_command("g.gisenv", stdout = subprocess.PIPE)
+    >>> print p
+    <subprocess.Popen object at 0xb7c12f6c>
+    >>> print p.communicate()[0]
+    GISDBASE='/opt/grass-data';
+    LOCATION_NAME='spearfish60';
+    MAPSET='glynn';
+    GRASS_DB_ENCODING='ascii';
+    GUI='text';
+    MONITOR='x0';
+    \endcode
+
+    @param prog GRASS module
+    @param flags flags to be used (given as a string)
+    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
+    @param quiet True to run quietly (<tt>--q</tt>)
+    @param verbose True to run verbosely (<tt>--v</tt>)
+    @param kwargs module's parameters
+
+    @return Popen object
+    """
+    options = {}
+    popts = {}
+    for opt, val in kwargs.iteritems():
+	if opt in _popen_args:
+	    popts[opt] = val
+	else:
+	    options[opt] = val
+
+    args = make_command(prog, flags, overwrite, quiet, verbose, **options)
+
+    if debug_level() > 0:
+        sys.stderr.write("D1/%d: %s.start_command(): %s\n" % (debug_level(), __name__, ' '.join(args)))
+        sys.stderr.flush()
+
+    return Popen(args, **popts)
+
+def run_command(*args, **kwargs):
+    """!Passes all arguments to start_command(), then waits for the process to
+    complete, returning its exit code. Similar to subprocess.call(), but
+    with the make_command() interface.
+
+    @param args list of unnamed arguments (see start_command() for details)
+    @param kwargs list of named arguments (see start_command() for details)
+
+    @return exit code (0 for success)
+    """
+    ps = start_command(*args, **kwargs)
+    return ps.wait()
+
+def pipe_command(*args, **kwargs):
+    """!Passes all arguments to start_command(), but also adds
+    "stdout = PIPE". Returns the Popen object.
+
+    \code
+    >>> p = grass.pipe_command("g.gisenv")
+    >>> print p
+    <subprocess.Popen object at 0xb7c12f6c>
+    >>> print p.communicate()[0]
+    GISDBASE='/opt/grass-data';
+    LOCATION_NAME='spearfish60';
+    MAPSET='glynn';
+    GRASS_DB_ENCODING='ascii';
+    GUI='text';
+    MONITOR='x0';
+    \endcode
+
+    @param args list of unnamed arguments (see start_command() for details)
+    @param kwargs list of named arguments (see start_command() for details)
+
+    @return Popen object
+    """
+    kwargs['stdout'] = PIPE
+    return start_command(*args, **kwargs)
+
+def feed_command(*args, **kwargs):
+    """!Passes all arguments to start_command(), but also adds
+    "stdin = PIPE". Returns the Popen object.
+
+    @param args list of unnamed arguments (see start_command() for details)
+    @param kwargs list of named arguments (see start_command() for details)
+
+    @return Popen object
+    """
+    kwargs['stdin'] = PIPE
+    return start_command(*args, **kwargs)
+
+def read_command(*args, **kwargs):
+    """!Passes all arguments to pipe_command, then waits for the process to
+    complete, returning its stdout (i.e. similar to shell `backticks`).
+
+    @param args list of unnamed arguments (see start_command() for details)
+    @param kwargs list of named arguments (see start_command() for details)
+
+    @return stdout
+    """
+    ps = pipe_command(*args, **kwargs)
+    return ps.communicate()[0]
+
+def parse_command(*args, **kwargs):
+    """!Passes all arguments to read_command, then parses the output
+    by parse_key_val().
+
+    Parsing function can be optionally given by <em>parse</em> parameter
+    including its arguments, e.g.
+
+    @code
+    parse_command(..., parse = (grass.parse_key_val, { 'sep' : ':' }))
+    @endcode
+
+    or you can simply define <em>delimiter</em>
+
+    @code
+    parse_command(..., delimiter = ':')
+    @endcode
+
+    @param args list of unnamed arguments (see start_command() for details)
+    @param kwargs list of named arguments (see start_command() for details)
+
+    @return parsed module output
+    """
+    parse = None
+    parse_args = {}
+    if 'parse' in kwargs:
+        if type(kwargs['parse']) is types.TupleType:
+            parse = kwargs['parse'][0]
+            parse_args = kwargs['parse'][1]
+        del kwargs['parse']
+
+    if 'delimiter' in kwargs:
+        parse_args = { 'sep' : kwargs['delimiter'] }
+        del kwargs['delimiter']
+
+    if not parse:
+        parse = parse_key_val # use default fn
+
+    res = read_command(*args, **kwargs)
+
+    return parse(res, **parse_args)
+
+def write_command(*args, **kwargs):
+    """!Passes all arguments to feed_command, with the string specified
+    by the 'stdin' argument fed to the process' stdin.
+
+    @param args list of unnamed arguments (see start_command() for details)
+    @param kwargs list of named arguments (see start_command() for details)
+
+    @return return code
+    """
+    stdin = kwargs['stdin']
+    p = feed_command(*args, **kwargs)
+    p.stdin.write(stdin)
+    p.stdin.close()
+    return p.wait()
+
+def exec_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, env = None, **kwargs):
+    """!Interface to os.execvpe(), but with the make_command() interface.
+
+    @param prog GRASS module
+    @param flags flags to be used (given as a string)
+    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
+    @param quiet True to run quietly (<tt>--q</tt>)
+    @param verbose True to run verbosely (<tt>--v</tt>)
+    @param env directory with environmental variables
+    @param kwargs module's parameters
+
+    """
+    args = make_command(prog, flags, overwrite, quiet, verbose, **kwargs)
+    if env == None:
+	env = os.environ
+    os.execvpe(prog, args, env)
+
+# interface to g.message
+
+def message(msg, flag = None):
+    """!Display a message using `g.message`
+
+    @param msg message to be displayed
+    @param flag flags (given as string)
+    """
+    run_command("g.message", flags = flag, message = msg)
+
+def debug(msg, debug = 1):
+    """!Display a debugging message using `g.message -d`
+
+    @param msg debugging message to be displayed
+    @param debug debug level (0-5)
+    """
+    run_command("g.message", flags = 'd', message = msg, debug = debug)
+
+def verbose(msg):
+    """!Display a verbose message using `g.message -v`
+
+    @param msg verbose message to be displayed
+    """
+    message(msg, flag = 'v')
+
+def info(msg):
+    """!Display an informational message using `g.message -i`
+
+    @param msg informational message to be displayed
+    """
+    message(msg, flag = 'i')
+
+def percent(i, n, s):
+    """!Display a progress info message using `g.message -p`
+
+    @code
+    message(_("Percent complete..."))
+    n = 100
+    for i in range(n):
+        percent(i, n, 1)
+    percent(1, 1, 1)
+    @endcode
+
+    @param i current item
+    @param n total number of items
+    @param s increment size
+    """
+    message("%d %d %d" % (i, n, s), flag = 'p')
+
+def warning(msg):
+    """!Display a warning message using `g.message -w`
+
+    @param msg warning message to be displayed
+    """
+    message(msg, flag = 'w')
+
+def error(msg):
+    """!Display an error message using `g.message -e`
+
+    @param msg error message to be displayed
+    """
+    message(msg, flag = 'e')
+
+def fatal(msg):
+    """!Display an error message using `g.message -e`, then abort
+
+    Raise exception when raise_on_error is 'True'.
+
+    @param msg error message to be displayed
+    """
+    global raise_on_error
+    if raise_on_error:
+        raise ScriptError(msg)
+
+    error(msg)
+    sys.exit(1)
+
+def set_raise_on_error(raise_exp = True):
+    """!Define behaviour on fatal error (fatal() called)
+
+    @param raise_exp True to raise ScriptError instead of calling
+    sys.exit(1) in fatal()
+
+    @return current status
+    """
+    global raise_on_error
+    tmp_raise = raise_on_error
+    raise_on_error = raise_exp
+    return tmp_raise
+
+# interface to g.parser
+
+def _parse_opts(lines):
+    options = {}
+    flags = {}
+    for line in lines:
+	line = line.rstrip('\r\n')
+	if not line:
+	    break
+	try:
+	    [var, val] = line.split('=', 1)
+	except:
+	    raise SyntaxError("invalid output from g.parser: %s" % line)
+
+	if var.startswith('flag_'):
+	    flags[var[5:]] = bool(int(val))
+	elif var.startswith('opt_'):
+	    options[var[4:]] = val
+	elif var in ['GRASS_OVERWRITE', 'GRASS_VERBOSE']:
+	    os.environ[var] = val
+	else:
+	    raise SyntaxError("invalid output from g.parser: %s" % line)
+
+    return (options, flags)
+
+def parser():
+    """!Interface to g.parser, intended to be run from the top-level, e.g.:
+
+    @code
+	if __name__ == "__main__":
+	    options, flags = grass.parser()
+	    main()
+    @endcode
+
+    Thereafter, the global variables "options" and "flags" will be
+    dictionaries containing option/flag values, keyed by lower-case
+    option/flag names. The values in "options" are strings, those in
+    "flags" are Python booleans.
+    """
+    if not os.getenv("GISBASE"):
+        print >> sys.stderr, "You must be in GRASS GIS to run this program."
+        sys.exit(1)
+
+    cmdline = [basename(sys.argv[0])]
+    cmdline += ['"' + arg + '"' for arg in sys.argv[1:]]
+    os.environ['CMDLINE'] = ' '.join(cmdline)
+
+    argv = sys.argv[:]
+    name = argv[0]
+    if not os.path.isabs(name):
+	if os.sep in name or (os.altsep and os.altsep in name):
+	    argv[0] = os.path.abspath(name)
+	else:
+	    argv[0] = os.path.join(sys.path[0], name)
+
+    p = Popen(['g.parser', '-s'] + argv, stdout = PIPE)
+    s = p.communicate()[0]
+    lines = s.splitlines()
+
+    if not lines or lines[0].rstrip('\r\n') != "@ARGS_PARSED@":
+        sys.stdout.write(s)
+        sys.exit(p.returncode)
+
+    return _parse_opts(lines[1:])
+
+# interface to g.tempfile
+
+def tempfile(create = True):
+    """!Returns the name of a temporary file, created with
+    g.tempfile.
+
+    @param create True to create a file
+
+    @return path to a tmp file
+    """
+    flags = ''
+    if not create:
+        flags += 'd'
+
+    return read_command("g.tempfile", flags = flags, pid = os.getpid()).strip()
+
+def tempdir():
+    """!Returns the name of a temporary dir, created with g.tempfile."""
+    tmp = tempfile(create = False)
+    os.mkdir(tmp)
+
+    return tmp
+
+class KeyValue(dict):
+    """A general-purpose key-value store.
+
+    KeyValue is a subclass of dict, but also allows entries to be read and
+    written using attribute syntax. Example:
+
+    \code
+    >>> region = grass.region()
+    >>> region['rows']
+    477
+    >>> region.rows
+    477
+    \endcode
+    """
+
+    def __getattr__(self, key):
+        return self[key]
+
+    def __setattr__(self, key, value):
+        self[key] = value
+
+# key-value parsers
+
+def parse_key_val(s, sep = '=', dflt = None, val_type = None, vsep = None):
+    """!Parse a string into a dictionary, where entries are separated
+    by newlines and the key and value are separated by `sep' (default: `=')
+
+    @param s string to be parsed
+    @param sep key/value separator
+    @param dflt default value to be used
+    @param val_type value type (None for no cast)
+    @param vsep vertical separator (default os.linesep)
+
+    @return parsed input (dictionary of keys/values)
+    """
+    result = KeyValue()
+
+    if not s:
+        return result
+
+    if vsep:
+        lines = s.split(vsep)
+        try:
+            lines.remove('\n')
+        except ValueError:
+            pass
+    else:
+        lines = s.splitlines()
+
+    for line in lines:
+	kv = line.split(sep, 1)
+	k = kv[0].strip()
+	if len(kv) > 1:
+	    v = kv[1].strip()
+	else:
+	    v = dflt
+
+        if val_type:
+            result[k] = val_type(v)
+        else:
+            result[k] = v
+
+    return result
+
+def _text_to_key_value_dict(filename, sep=":", val_sep=","):
+    """
+        !Convert a key-value text file, where entries are separated
+        by newlines and the key and value are separated by `sep',
+        into a key-value dictionary and discover/use the correct
+        data types (float, int or string) for values.
+
+        @param filename The name or name and path of the text file to convert
+        @param sep The character that separates the keys and values, default is ":"
+        @param val_sep The character that separates the values of a single key, default is ","
+        @return The dictionary
+
+        A text file with this content:
+        \code
+        a: Hello
+        b: 1.0
+        c: 1,2,3,4,5
+        d : hello,8,0.1
+        \endcode
+
+        Will be represented as this dictionary:
+        \code
+        {'a': ['Hello'], 'c': [1, 2, 3, 4, 5], 'b': [1.0], 'd': ['hello', 8, 0.1]}
+        \endcode
+
+    """
+    text = open(filename, "r").readlines()
+    kvdict = KeyValue()
+
+    for line in text:
+        if line.find(sep) >= 0:
+            key, value = line.split(sep)
+            key = key.strip()
+            value = value.strip()
+        else:
+            # Jump over empty values
+            continue
+        values = value.split(val_sep)
+        value_list = []
+
+        for value in values:
+            not_float = False
+            not_int = False
+
+            # Convert values into correct types
+            # We first try integer then float
+            try:
+                value_converted = int(value)
+            except:
+                not_int = True
+            if not_int:
+                try:
+                    value_converted = float(value)
+                except:
+                    not_float = True
+
+            if not_int and not_float:
+                value_converted = value.strip()
+
+            value_list.append(value_converted)
+
+        kvdict[key] = value_list
+    return kvdict
+
+def compare_key_value_text_files(filename_a, filename_b, sep=":",
+                                 val_sep=",", precision=0.000001):
+    """
+        !Compare two key-value text files that may contain projection parameter
+
+        @param filename_a The name of the first key-value text file
+        @param filenmae_b The name of the second key-value text file
+        @param sep The character that separates the keys and values, default is ":"
+        @param val_sep The character that separates the values of a single key, default is ","
+        @param precision The precision with which the floating point values are compares
+           if abs(a - b) > precision : return False
+        @return True if full or almost identical, False if different
+
+        This method will print a warning in case keys that are present in the first file
+        are not present in the second one.
+        The comparison method tries to convert the values into there native format (float, int or string)
+        to allow correct comparison.
+
+        An example key-value text file may have this content:
+        \code
+        a: Hello
+        b: 1.0
+        c: 1,2,3,4,5
+        d : hello,8,0.1
+        \endcode
+    """
+    dict_a = _text_to_key_value_dict(filename_a, sep)
+    dict_b = _text_to_key_value_dict(filename_b, sep)
+
+    missing_keys = 0
+
+    # We compare matching keys
+    for key in dict_a.keys():
+        if dict_b.has_key(key):
+            # Floating point values must be handled separately
+            if isinstance(dict_a[key], float) and isinstance(dict_b[key], float):
+                if abs(dict_a[key] - dict_b[key]) > precision:
+                    return False
+            elif isinstance(dict_a[key], float) or isinstance(dict_b[key], float):
+                return False
+            else:
+                if dict_a[key] != dict_b[key]:
+                    return False
+        else:
+            missing_keys += 1
+    if missing_keys == len(dict_a):
+        return False
+    if missing_keys > 0:
+        warning(_("Several keys (%i out of %i) are missing "
+                  "in the target file")%(missing_keys, len(dict_a)))
+    return True
+
+# interface to g.gisenv
+
+def gisenv():
+    """!Returns the output from running g.gisenv (with no arguments), as a
+    dictionary. Example:
+
+    \code
+    >>> env = grass.gisenv()
+    >>> print env['GISDBASE']
+    /opt/grass-data
+    \endcode
+
+    @return list of GRASS variables
+    """
+    s = read_command("g.gisenv", flags='n')
+    return parse_key_val(s)
+
+# interface to g.region
+
+def locn_is_latlong():
+    """!Tests if location is lat/long. Value is obtained
+    by checking the "g.region -p" projection code.
+
+    @return True for a lat/long region, False otherwise
+    """
+    s = read_command("g.region", flags='p')
+    kv = parse_key_val(s, ':')
+    if kv['projection'].split(' ')[1] == '3':
+	return True
+    else:
+	return False
+
+def region(region3d = False, complete = False):
+    """!Returns the output from running "g.region -g", as a
+    dictionary. Example:
+
+    \param region3d True to get 3D region
+
+    \code
+    >>> region = grass.region()
+    >>> [region[key] for key in "nsew"]
+    [228500.0, 215000.0, 645000.0, 630000.0]
+    >>> (region['nsres'], region['ewres'])
+    (10.0, 10.0)
+    \endcode
+
+    @return dictionary of region values
+    """
+    flgs = 'g'
+    if region3d:
+        flgs += '3'
+    if complete:
+        flgs += 'cep'
+
+    s = read_command("g.region", flags = flgs)
+    reg = parse_key_val(s, val_type = float)
+    for k in ['rows',  'cols',  'cells',
+              'rows3', 'cols3', 'cells3', 'depths']:
+        if k not in reg:
+            continue
+	reg[k] = int(reg[k])
+
+    return reg
+
+def region_env(region3d = False,
+               **kwargs):
+    """!Returns region settings as a string which can used as
+    GRASS_REGION environmental variable.
+
+    If no 'kwargs' are given then the current region is used. Note
+    that this function doesn't modify the current region!
+
+    See also use_temp_region() for alternative method how to define
+    temporary region used for raster-based computation.
+
+    \param region3d True to get 3D region
+    \param kwargs g.region's parameters like 'rast', 'vect' or 'region'
+    \code
+    os.environ['GRASS_REGION'] = grass.region_env(region = 'detail')
+    grass.mapcalc('map = 1', overwrite = True)
+    os.environ.pop('GRASS_REGION')
+    \endcode
+
+    @return string with region values
+    @return empty string on error
+    """
+    # read proj/zone from WIND file
+    env = gisenv()
+    windfile = os.path.join (env['GISDBASE'], env['LOCATION_NAME'],
+                              env['MAPSET'], "WIND")
+    fd = open(windfile, "r")
+    grass_region = ''
+    for line in fd.readlines():
+        key, value = map(lambda x: x.strip(), line.split(":", 1))
+        if kwargs and key not in ('proj', 'zone'):
+            continue
+        if not kwargs and not region3d and \
+                key in ('top', 'bottom', 'cols3', 'rows3',
+                        'depths', 'e-w resol3', 'n-s resol3', 't-b resol'):
+            continue
+
+        grass_region += '%s: %s;' % (key, value)
+
+    if not kwargs: # return current region
+        return grass_region
+
+    # read other values from `g.region -g`
+    flgs = 'ug'
+    if region3d:
+        flgs += '3'
+
+    s = read_command('g.region', flags = flgs, **kwargs)
+    if not s:
+        return ''
+    reg = parse_key_val(s)
+
+    kwdata = [('north',     'n'),
+              ('south',     's'),
+              ('east',      'e'),
+              ('west',      'w'),
+              ('cols',      'cols'),
+              ('rows',      'rows'),
+              ('e-w resol', 'ewres'),
+              ('n-s resol', 'nsres')]
+    if region3d:
+        kwdata += [('top',        't'),
+                   ('bottom',     'b'),
+                   ('cols3',      'cols3'),
+                   ('rows3',      'rows3'),
+                   ('depths',     'depths'),
+                   ('e-w resol3', 'ewres3'),
+                   ('n-s resol3', 'nsres3'),
+                   ('t-b resol',  'tbres')]
+
+    for wkey, rkey in kwdata:
+        grass_region += '%s: %s;' % (wkey, reg[rkey])
+
+    return grass_region
+
+def use_temp_region():
+    """!Copies the current region to a temporary region with "g.region save=",
+    then sets WIND_OVERRIDE to refer to that region. Installs an atexit
+    handler to delete the temporary region upon termination.
+    """
+    name = "tmp.%s.%d" % (os.path.basename(sys.argv[0]), os.getpid())
+    run_command("g.region", save = name, overwrite = True)
+    os.environ['WIND_OVERRIDE'] = name
+    atexit.register(del_temp_region)
+
+def del_temp_region():
+    """!Unsets WIND_OVERRIDE and removes any region named by it."""
+    try:
+	name = os.environ.pop('WIND_OVERRIDE')
+	run_command("g.remove", quiet = True, region = name)
+    except:
+	pass
+
+# interface to g.findfile
+
+def find_file(name, element = 'cell', mapset = None):
+    """!Returns the output from running g.findfile as a
+    dictionary. Example:
+
+    \code
+    >>> result = grass.find_file('fields', element = 'vector')
+    >>> print result['fullname']
+    fields at PERMANENT
+    >>> print result['file']
+    /opt/grass-data/spearfish60/PERMANENT/vector/fields
+    \endcode
+
+    @param name file name
+    @param element element type (default 'cell')
+    @param mapset mapset name (default all mapsets in search path)
+
+    @return parsed output of g.findfile
+    """
+    if element == 'raster' or element == 'rast':
+        verbose(_('Element type should be "cell" and not "%s"') % element)
+        element = 'cell'
+    s = read_command("g.findfile", flags='n', element = element, file = name, mapset = mapset)
+    return parse_key_val(s)
+
+# interface to g.list
+
+def list_grouped(type, check_search_path = True):
+    """!List elements grouped by mapsets.
+
+    Returns the output from running g.list, as a dictionary where the
+    keys are mapset names and the values are lists of maps in that
+    mapset. Example:
+
+    @code
+    >>> grass.list_grouped('rast')['PERMANENT']
+    ['aspect', 'erosion1', 'quads', 'soils', 'strm.dist', ...
+    @endcode
+
+    @param type element type (rast, vect, rast3d, region, ...)
+    @param check_search_path True to add mapsets for the search path with no found elements
+
+    @return directory of mapsets/elements
+    """
+    if type == 'raster' or type == 'cell':
+        verbose(_('Element type should be "rast" and not "%s"') % element)
+        type = 'rast'
+    dashes_re = re.compile("^----+$")
+    mapset_re = re.compile("<(.*)>")
+    result = {}
+    if check_search_path:
+        for mapset in mapsets(search_path = True):
+            result[mapset] = []
+
+    mapset = None
+    for line in read_command("g.list", type = type).splitlines():
+	if line == "":
+	    continue
+	if dashes_re.match(line):
+	    continue
+	m = mapset_re.search(line)
+	if m:
+	    mapset = m.group(1)
+            if mapset not in result.keys():
+                result[mapset] = []
+	    continue
+        if mapset:
+            result[mapset].extend(line.split())
+
+    return result
+
+def _concat(xs):
+    result = []
+    for x in xs:
+	result.extend(x)
+    return result
+
+def list_pairs(type):
+    """!List of elements as tuples.
+
+    Returns the output from running g.list, as a list of (map, mapset)
+    pairs. Example:
+
+    @code
+    >>> grass.list_pairs('rast')
+    [('aspect', 'PERMANENT'), ('erosion1', 'PERMANENT'), ('quads', 'PERMANENT'), ...
+    @endcode
+
+    @param type element type (rast, vect, rast3d, region, ...)
+
+    @return list of tuples (map, mapset)
+    """
+    return _concat([[(map, mapset) for map in maps]
+		    for mapset, maps in list_grouped(type).iteritems()])
+
+def list_strings(type):
+    """!List of elements as strings.
+
+    Returns the output from running g.list, as a list of qualified
+    names. Example:
+
+    @code
+    >>> grass.list_strings('rast')
+    ['aspect at PERMANENT', 'erosion1 at PERMANENT', 'quads at PERMANENT', 'soils at PERMANENT', ...
+    @endcode
+
+    @param type element type
+
+    @return list of strings ('map@@mapset')
+    """
+    return ["%s@%s" % pair for pair in list_pairs(type)]
+
+# interface to g.mlist
+
+def mlist_strings(type, pattern = None, mapset = None, flag = ''):
+    """!List of elements as strings.
+
+    Returns the output from running g.mlist, as a list of qualified
+    names.
+
+    @param type element type (rast, vect, rast3d, region, ...)
+    @param pattern pattern string
+    @param mapset mapset name (if not given use search path)
+    @param flag pattern type: 'r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
+
+    @return list of elements
+    """
+    if type == 'raster' or type == 'cell':
+        verbose(_('Element type should be "rast" and not "%s"') % element)
+        type = 'rast'
+    result = list()
+    for line in read_command("g.mlist",
+                             quiet = True,
+                             flags = 'm' + flag,
+                             type = type,
+                             pattern = pattern,
+                             mapset = mapset).splitlines():
+        result.append(line.strip())
+
+    return result
+
+def mlist_pairs(type, pattern = None, mapset = None, flag = ''):
+    """!List of elements as pairs
+
+    Returns the output from running g.mlist, as a list of
+    (name, mapset) pairs
+
+    @param type element type (rast, vect, rast3d, region, ...)
+    @param pattern pattern string
+    @param mapset mapset name (if not given use search path)
+    @param flag pattern type: 'r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
+
+    @return list of elements
+    """
+    return [tuple(map.split('@', 1)) for map in mlist_strings(type, pattern, mapset, flag)]
+
+def mlist_grouped(type, pattern = None, check_search_path = True, flag = ''):
+    """!List of elements grouped by mapsets.
+
+    Returns the output from running g.mlist, as a dictionary where the
+    keys are mapset names and the values are lists of maps in that
+    mapset. Example:
+
+    @code
+    >>> grass.mlist_grouped('rast', pattern='r*')['PERMANENT']
+    ['railroads', 'roads', 'rstrct.areas', 'rushmore']
+    @endcode
+
+    @param type element type (rast, vect, rast3d, region, ...)
+    @param pattern pattern string
+    @param check_search_path True to add mapsets for the search path with no found elements
+    @param flag pattern type: 'r' (basic regexp), 'e' (extended regexp), or '' (glob pattern)
+
+    @return directory of mapsets/elements
+    """
+    if type == 'raster' or type == 'cell':
+        verbose(_('Element type should be "rast" and not "%s"') % element)
+        type = 'rast'
+    result = {}
+    if check_search_path:
+        for mapset in mapsets(search_path = True):
+            result[mapset] = []
+
+    mapset = None
+    for line in read_command("g.mlist", quiet = True, flags = "m" + flag,
+                             type = type, pattern = pattern).splitlines():
+        try:
+            name, mapset = line.split('@')
+        except ValueError:
+            warning(_("Invalid element '%s'") % line)
+            continue
+
+        if mapset in result:
+            result[mapset].append(name)
+        else:
+            result[mapset] = [name, ]
+
+    return result
+
+# color parsing
+
+named_colors = {
+    "white":   (1.00, 1.00, 1.00),
+    "black":   (0.00, 0.00, 0.00),
+    "red":     (1.00, 0.00, 0.00),
+    "green":   (0.00, 1.00, 0.00),
+    "blue":    (0.00, 0.00, 1.00),
+    "yellow":  (1.00, 1.00, 0.00),
+    "magenta": (1.00, 0.00, 1.00),
+    "cyan":    (0.00, 1.00, 1.00),
+    "aqua":    (0.00, 0.75, 0.75),
+    "grey":    (0.75, 0.75, 0.75),
+    "gray":    (0.75, 0.75, 0.75),
+    "orange":  (1.00, 0.50, 0.00),
+    "brown":   (0.75, 0.50, 0.25),
+    "purple":  (0.50, 0.00, 1.00),
+    "violet":  (0.50, 0.00, 1.00),
+    "indigo":  (0.00, 0.50, 1.00)}
+
+def parse_color(val, dflt = None):
+    """!Parses the string "val" as a GRASS colour, which can be either one of
+    the named colours or an R:G:B tuple e.g. 255:255:255. Returns an
+    (r,g,b) triple whose components are floating point values between 0
+    and 1. Example:
+
+    \code
+    >>> grass.parse_color("red")
+    (1.0, 0.0, 0.0)
+    >>> grass.parse_color("255:0:0")
+    (1.0, 0.0, 0.0)
+    \endcode
+
+    @param val color value
+    @param dflt default color value
+
+    @return tuple RGB
+    """
+    if val in named_colors:
+        return named_colors[val]
+
+    vals = val.split(':')
+    if len(vals) == 3:
+        return tuple(float(v) / 255 for v in vals)
+
+    return dflt
+
+# check GRASS_OVERWRITE
+
+def overwrite():
+    """!Return True if existing files may be overwritten"""
+    owstr = 'GRASS_OVERWRITE'
+    return owstr in os.environ and os.environ[owstr] != '0'
+
+# check GRASS_VERBOSE
+
+def verbosity():
+    """!Return the verbosity level selected by GRASS_VERBOSE"""
+    vbstr = os.getenv('GRASS_VERBOSE')
+    if vbstr:
+	return int(vbstr)
+    else:
+	return 2
+
+## various utilities, not specific to GRASS
+
+# basename inc. extension stripping
+
+def basename(path, ext = None):
+    """!Remove leading directory components and an optional extension
+    from the specified path
+
+    @param path path
+    @param ext extension
+    """
+    name = os.path.basename(path)
+    if not ext:
+	return name
+    fs = name.rsplit('.', 1)
+    if len(fs) > 1 and fs[1].lower() == ext:
+	name = fs[0]
+    return name
+
+# find a program (replacement for "which")
+
+def find_program(pgm, args = []):
+    """!Attempt to run a program, with optional arguments.
+
+    @param pgm program name
+    @param args list of arguments
+
+    @return False if the attempt failed due to a missing executable
+    @return True otherwise
+    """
+    nuldev = file(os.devnull, 'w+')
+    try:
+	ret = call([pgm] + args, stdin = nuldev, stdout = nuldev, stderr = nuldev)
+        if ret == 0:
+            found = True
+        else:
+            found = False
+    except:
+	found = False
+    nuldev.close()
+
+    return found
+
+# try to remove a file, without complaints
+
+def try_remove(path):
+    """!Attempt to remove a file; no exception is generated if the
+    attempt fails.
+
+    @param path path to file to remove
+    """
+    try:
+	os.remove(path)
+    except:
+	pass
+
+# try to remove a directory, without complaints
+
+def try_rmdir(path):
+    """!Attempt to remove a directory; no exception is generated if the
+    attempt fails.
+
+    @param path path to directory to remove
+    """
+    try:
+	os.rmdir(path)
+    except:
+	shutil.rmtree(path, ignore_errors = True)
+
+def float_or_dms(s):
+    """!Convert DMS to float.
+
+    @param s DMS value
+
+    @return float value
+    """
+    return sum(float(x) / 60 ** n for (n, x) in enumerate(s.split(':')))
+
+# interface to g.mapsets
+
+def mapsets(search_path = False):
+    """!List available mapsets
+
+    @param search_path True to list mapsets only in search path
+
+    @return list of mapsets
+    """
+    if search_path:
+        flags = 'p'
+    else:
+        flags = 'l'
+    mapsets = read_command('g.mapsets',
+                           flags = flags,
+                           sep = 'newline',
+                           quiet = True)
+    if not mapsets:
+        fatal(_("Unable to list mapsets"))
+
+    return mapsets.splitlines()
+
+# interface to `g.proj -c`
+
+def create_location(dbase, location,
+                    epsg = None, proj4 = None, filename = None, wkt = None,
+                    datum = None, datum_trans = None, desc = None):
+    """!Create new location
+
+    Raise ScriptError on error.
+
+    @param dbase path to GRASS database
+    @param location location name to create
+    @param epsg if given create new location based on EPSG code
+    @param proj4 if given create new location based on Proj4 definition
+    @param filename if given create new location based on georeferenced file
+    @param wkt if given create new location based on WKT definition (path to PRJ file)
+    @param datum GRASS format datum code
+    @param datum_trans datum transformation parameters (used for epsg and proj4)
+    @param desc description of the location (creates MYNAME file)
+    """
+    gisdbase = None
+    if epsg or proj4 or filename or wkt:
+        gisdbase = gisenv()['GISDBASE']
+        run_command('g.gisenv',
+                    set = 'GISDBASE=%s' % dbase)
+    if not os.path.exists(dbase):
+            os.mkdir(dbase)
+
+    kwargs = dict()
+    if datum:
+        kwargs['datum'] = datum
+    if datum_trans:
+        kwargs['datum_trans'] = datum_trans
+
+    if epsg:
+        ps = pipe_command('g.proj',
+                          quiet = True,
+                          epsg = epsg,
+                          location = location,
+                          stderr = PIPE,
+                          **kwargs)
+    elif proj4:
+        ps = pipe_command('g.proj',
+                          quiet = True,
+                          proj4 = proj4,
+                          location = location,
+                          stderr = PIPE,
+                          **kwargs)
+    elif filename:
+        ps = pipe_command('g.proj',
+                          quiet = True,
+                          georef = filename,
+                          location = location,
+                          stderr = PIPE)
+    elif wkt:
+        ps = pipe_command('g.proj',
+                          quiet = True,
+                          wkt = wkt,
+                          location = location,
+                          stderr = PIPE)
+    else:
+        _create_location_xy(dbase, location)
+
+    if epsg or proj4 or filename or wkt:
+        error = ps.communicate()[1]
+        run_command('g.gisenv',
+                    set = 'GISDBASE=%s' % gisdbase)
+
+        if ps.returncode != 0 and error:
+            raise ScriptError(repr(error))
+
+    try:
+        fd = codecs.open(os.path.join(dbase, location,
+                                      'PERMANENT', 'MYNAME'),
+                         encoding = 'utf-8', mode = 'w')
+        if desc:
+            fd.write(desc + os.linesep)
+        else:
+            fd.write(os.linesep)
+        fd.close()
+    except OSError, e:
+        raise ScriptError(repr(e))
+
+def _create_location_xy(database, location):
+    """!Create unprojected location
+
+    Raise ScriptError on error.
+
+    @param database GRASS database where to create new location
+    @param location location name
+    """
+    cur_dir = os.getcwd()
+    try:
+        os.chdir(database)
+        os.mkdir(location)
+        os.mkdir(os.path.join(location, 'PERMANENT'))
+
+        # create DEFAULT_WIND and WIND files
+        regioninfo = ['proj:       0',
+                      'zone:       0',
+                      'north:      1',
+                      'south:      0',
+                      'east:       1',
+                      'west:       0',
+                      'cols:       1',
+                      'rows:       1',
+                      'e-w resol:  1',
+                      'n-s resol:  1',
+                      'top:        1',
+                      'bottom:     0',
+                      'cols3:      1',
+                      'rows3:      1',
+                      'depths:     1',
+                      'e-w resol3: 1',
+                      'n-s resol3: 1',
+                      't-b resol:  1']
+
+        defwind = open(os.path.join(location,
+                                    "PERMANENT", "DEFAULT_WIND"), 'w')
+        for param in regioninfo:
+            defwind.write(param + '%s' % os.linesep)
+        defwind.close()
+
+        shutil.copy(os.path.join(location, "PERMANENT", "DEFAULT_WIND"),
+                    os.path.join(location, "PERMANENT", "WIND"))
+
+        os.chdir(cur_dir)
+    except OSError, e:
+        raise ScriptError(repr(e))
+
+# interface to g.version
+
+def version():
+    """!Get GRASS version as dictionary
+
+    @code
+    print version()
+
+    {'proj4': '4.8.0', 'geos': '3.3.5', 'libgis_revision': '52468',
+     'libgis_date': '2012-07-27 22:53:30 +0200 (Fri, 27 Jul 2012)',
+     'version': '7.0.svn', 'date': '2012', 'gdal': '2.0dev', 'revision': '53670'}
+    @endcode
+    """
+    data = parse_command('g.version',
+                         flags = 'rge')
+    for k, v in data.iteritems():
+        data[k.strip()] = v.replace('"', '').strip()
+
+    return data
+
+# get debug_level
+_debug_level = None
+
+def debug_level():
+    global _debug_level
+    if _debug_level is not None:
+        return _debug_level
+    _debug_level = 0
+    if find_program('g.gisenv', ['--help']):
+        _debug_level = int(gisenv().get('DEBUG', 0))

Copied: grass/trunk/lib/python/script/db.py (from rev 54568, grass/trunk/lib/python/db.py)
===================================================================
--- grass/trunk/lib/python/script/db.py	                        (rev 0)
+++ grass/trunk/lib/python/script/db.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,155 @@
+"""!@package grass.script.db
+
+ at brief GRASS Python scripting module (database functions)
+
+Database related functions to be used in Python scripts.
+
+Usage:
+
+ at code
+from grass.script import db as grass
+
+grass.db_describe(table)
+...
+ at endcode
+
+(C) 2008-2009, 2012 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Glynn Clements
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import tempfile as pytempfile # conflict with core.tempfile
+
+from core import *
+
+def db_describe(table, **args):
+    """!Return the list of columns for a database table
+    (interface to `db.describe -c'). Example:
+
+    \code
+    >>> grass.db_describe('lakes')
+    {'nrows': 15279, 'cols': [['cat', 'INTEGER', '11'], ['AREA', 'DOUBLE PRECISION', '20'],
+    ['PERIMETER', 'DOUBLE PRECISION', '20'], ['FULL_HYDRO', 'DOUBLE PRECISION', '20'],
+    ['FULL_HYDR2', 'DOUBLE PRECISION', '20'], ['FTYPE', 'CHARACTER', '24'],
+    ['FCODE', 'INTEGER', '11'], ['NAME', 'CHARACTER', '99']], 'ncols': 8}
+    \endcode
+
+    @param table table name
+    @param args
+
+    @return parsed module output
+    """
+    s = read_command('db.describe', flags = 'c', table = table, **args)
+    if not s:
+        fatal(_("Unable to describe table <%s>") % table)
+    
+    cols = []
+    result = {}
+    for l in s.splitlines():
+        f = l.split(':')
+        key = f[0]
+        f[1] = f[1].lstrip(' ')
+        if key.startswith('Column '):
+            n = int(key.split(' ')[1])
+            cols.insert(n, f[1:])
+        elif key in ['ncols', 'nrows']:
+            result[key] = int(f[1])
+        else:
+            result[key] = f[1:]
+    result['cols'] = cols
+    
+    return result
+
+# run "db.connect -g" and parse output
+
+def db_table_exist(table, **args):
+    """!Return True if database table exists, False otherwise
+
+    @param table table name
+    @param args
+
+    @return True for success, False otherwise
+    """
+    result = run_command('db.describe', flags = 'c', table = table, **args)
+    if result == 0:
+            return True
+    else:
+            return False
+
+def db_connection():
+    """!Return the current database connection parameters
+    (interface to `db.connect -g'). Example:
+
+    \code
+    >>> grass.db_connection()
+    {'group': 'x', 'schema': '', 'driver': 'dbf', 'database': '$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/'}
+    \endcode
+
+    @return parsed output of db.connect
+    """
+    return parse_command('db.connect', flags = 'g')
+
+def db_select(sql = None, filename = None, table = None, **args):
+    """!Perform SQL select statement
+
+    Note: one of <em>sql</em>, <em>filename</em>, or <em>table</em>
+    arguments must be provided.
+    
+    Examples:
+    
+    \code
+    grass.db_select(sql = 'SELECT cat,CAMPUS FROM busstopsall WHERE cat < 4')
+
+    (('1', 'Vet School'), ('2', 'West'), ('3', 'North'))
+    \endcode
+    
+    \code
+     grass.db_select(filename = '/path/to/sql/file')
+    \endcode
+
+    Simplyfied usage 
+    
+    \code
+    grass.db_select(table = 'busstopsall')
+    \endcode
+
+    performs <tt>SELECT * FROM busstopsall</tt>.
+
+    @param sql SQL statement to perform (or None)
+    @param filename name of file with SQL statements (or None)
+    @param table name of table to query (or None)
+    @param args  see \gmod{db.select} arguments
+    """
+    fname = tempfile(create = False)
+    if sql:
+        args['sql'] = sql
+    elif filename:
+        args['input'] = filename
+    elif table:
+        args['table'] = table
+    else:
+        fatal(_("Programmer error: '%(sql)s', '%(filename)s', or '%(table)s' must be provided") %
+              {'sql': 'sql', 'filename': 'filename', 'table': 'table'} )
+    
+    if 'sep' not in args:
+        args['sep'] = '|'
+    
+    ret = run_command('db.select', quiet = True,
+                      flags = 'c',
+                      output = fname,
+                      **args)
+    
+    if ret != 0:
+        fatal(_("Fetching data failed"))
+    
+    ofile = open(fname)
+    result = map(lambda x: tuple(x.rstrip(os.linesep).split(args['sep'])),
+                 ofile.readlines())
+    ofile.close()
+    try_remove(fname)
+        
+    return tuple(result)

Copied: grass/trunk/lib/python/script/raster.py (from rev 54568, grass/trunk/lib/python/raster.py)
===================================================================
--- grass/trunk/lib/python/script/raster.py	                        (rev 0)
+++ grass/trunk/lib/python/script/raster.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,137 @@
+"""!@package grass.script.raster
+
+ at brief GRASS Python scripting module (raster functions)
+
+Raster related functions to be used in Python scripts.
+
+Usage:
+
+ at code
+from grass.script import raster as grass
+
+grass.raster_history(map)
+...
+ at endcode
+
+(C) 2008-2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Glynn Clements
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+import string
+
+from core import *
+
+# add raster history
+
+def raster_history(map):
+    """!Set the command history for a raster map to the command used to
+    invoke the script (interface to `r.support').
+
+    @param map map name
+
+    @return True on success
+    @return False on failure
+    """
+    current_mapset = gisenv()['MAPSET']
+    if find_file(name = map)['mapset'] == current_mapset:
+        run_command('r.support', map = map, history = os.environ['CMDLINE'])
+        return True
+    
+    warning(_("Unable to write history for <%(map)s>. "
+              "Raster map <%(map)s> not found in current mapset." % { 'map' : map, 'map' : map}))
+    return False
+
+# run "r.info -gre ..." and parse output
+
+def raster_info(map):
+    """!Return information about a raster map (interface to
+    `r.info'). Example:
+
+    \code
+    >>> grass.raster_info('elevation')
+    {'north': 228500.0, 'timestamp': '"none"', 'min': 55.578792572021499,
+    'datatype': 'FCELL', 'max': 156.32986450195301, 'ewres': 10.0,
+    'vertical_datum': '', 'west': 630000.0, 'units': '',
+    'title': 'South-West Wake county: Elevation NED 10m (elev_ned10m)',
+    'east': 645000.0, 'nsres': 10.0, 'south': 215000.0}
+    \endcode
+
+    @param map map name
+    
+    @return parsed raster info
+    """
+
+    def float_or_null(s):
+        if s == 'NULL':
+            return None
+        else:
+            return float(s)
+
+    s = read_command('r.info', flags = 'gre', map = map)
+    kv = parse_key_val(s)
+    for k in ['min', 'max']:
+	kv[k] = float_or_null(kv[k])
+    for k in ['north', 'south', 'east', 'west']:
+	kv[k] = float(kv[k])
+    for k in ['nsres', 'ewres']:
+	kv[k] = float_or_dms(kv[k])
+    return kv
+
+# interface to r.mapcalc
+
+def mapcalc(exp, quiet = False, verbose = False, overwrite = False, **kwargs):
+    """!Interface to r.mapcalc.
+
+    @param exp expression
+    @param quiet True to run quietly (<tt>--q</tt>)
+    @param verbose True to run verbosely (<tt>--v</tt>)
+    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
+    @param kwargs
+    """
+    t = string.Template(exp)
+    e = t.substitute(**kwargs)
+
+    if run_command('r.mapcalc', expression = e,
+                   quiet = quiet,
+                   verbose = verbose,
+                   overwrite = overwrite) != 0:
+	fatal(_("An error occurred while running r.mapcalc"))
+
+
+def mapcalc_start(exp, quiet = False, verbose = False, overwrite = False, **kwargs):
+    """!Interface to r.mapcalc, doesn't wait for it to finish, returns Popen object.
+
+    \code
+    >>> expr1 = '"%s" = "%s" * 10' % (output, input)
+    >>> expr2 = '...'   # etc.
+    >>> # launch the jobs:
+    >>> p1 = grass.mapcalc_start(expr1)
+    >>> p2 = grass.mapcalc_start(expr2)   # etc.
+    ...
+    >>> # wait for them to finish:
+    >>> p1.wait()
+    >>> p2.wait()   # etc.
+    \endcode
+
+    @param exp expression
+    @param quiet True to run quietly (<tt>--q</tt>)
+    @param verbose True to run verbosely (<tt>--v</tt>)
+    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
+    @param kwargs
+    
+    @return Popen object
+    """
+    t = string.Template(exp)
+    e = t.substitute(**kwargs)
+
+    return start_command('r.mapcalc', expression = e,
+                        quiet = quiet,
+                        verbose = verbose,
+                        overwrite = overwrite)
+

Copied: grass/trunk/lib/python/script/raster3d.py (from rev 54568, grass/trunk/lib/python/raster3d.py)
===================================================================
--- grass/trunk/lib/python/script/raster3d.py	                        (rev 0)
+++ grass/trunk/lib/python/script/raster3d.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,89 @@
+"""!@package grass.script.raster3d
+
+ at brief GRASS Python scripting module (raster3d functions)
+
+Raster3d related functions to be used in Python scripts.
+
+Usage:
+
+ at code
+from grass.script import raster3d as grass
+
+grass.raster3d_info(map)
+...
+ at endcode
+
+(C) 2008-2009 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Glynn Clements
+ at author Martin Landa <landa.martin gmail.com>
+ at author Soeren Gebbert <soeren.gebbert gmail.com>
+"""
+
+import os
+import string
+
+from core import *
+
+# add raster history
+
+# run "r3.info -rstgip ..." and parse output
+
+def raster3d_info(map):
+    """!Return information about a raster3d map (interface to
+    `r3.info'). Example:
+
+    \code
+    >>> grass.raster3d_info('volume')
+    {'tiledimz': 1, 'tbres': 1.0, 'tiledimx': 27, 'tiledimy': 16, 'north': 60.490001999999997, 'tilenumy': 1, 'tilenumz': 1, 
+    'min': 1.0, 'datatype': '"DCELL"', 'max': 1.0, 'top': 0.5, 'bottom': -0.5, 'west': -3.2200000000000002, 'tilenumx': 1, 
+    'ewres': 0.98222219, 'east': 23.299999, 'nsres': 0.99937511999999995, 'Timestamp': '"none"', 'south': 44.5}
+    \endcode
+
+    @param map map name
+    
+    @return parsed raster3d info
+    """
+
+    def float_or_null(s):
+        if s == 'NULL':
+            return None
+        else:
+            return float(s)
+
+    s = read_command('r3.info', flags='rg', map=map)
+    kv = parse_key_val(s)
+    for k in ['min', 'max']:
+	kv[k] = float_or_null(kv[k])
+    for k in ['north', 'south', 'east', 'west', 'top', 'bottom']:
+	kv[k] = float(kv[k])
+    for k in ['nsres', 'ewres', 'tbres']:
+	kv[k] = float_or_dms(kv[k])
+    for k in ['tilenumx', 'tilenumy', 'tilenumz']:
+	kv[k] = int(kv[k])
+    for k in ['tiledimx', 'tiledimy', 'tiledimz']:
+	kv[k] = int(kv[k])
+    return kv
+
+# interface to r3.mapcalc
+
+def mapcalc3d(exp, quiet = False, verbose = False, overwrite = False, **kwargs):
+    """!Interface to r3.mapcalc.
+
+    @param exp expression
+    @param quiet True to run quietly (<tt>--q</tt>)
+    @param verbose True to run verbosely (<tt>--v</tt>)
+    @param overwrite True to enable overwriting the output (<tt>--o</tt>)
+    @param kwargs
+    """
+    t = string.Template(exp)
+    e = t.substitute(**kwargs)
+
+    if run_command('r3.mapcalc', expression = e,
+                   quiet = quiet,
+                   verbose = verbose,
+                   overwrite = overwrite) != 0:
+	fatal(_("An error occurred while running r3.mapcalc"))

Copied: grass/trunk/lib/python/script/setup.py.sed (from rev 54568, grass/trunk/lib/python/setup.py.sed)
===================================================================
--- grass/trunk/lib/python/script/setup.py.sed	                        (rev 0)
+++ grass/trunk/lib/python/script/setup.py.sed	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,71 @@
+"""!@package grass.script.setup
+
+ at brief GRASS Python scripting module (setup)
+
+Setup functions to be used in Python scripts.
+
+Usage:
+
+ at code
+from grass.script import setup as grass
+
+grass.init()
+...
+ at endcode
+
+(C) 2010-2012 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+import sys
+import tempfile as tmpfile
+
+def init(gisbase, dbase = '', location = 'demolocation', mapset = 'PERMANENT'):
+    """!Initialize system variables to run scripts without starting
+    GRASS explicitly.
+
+    User is resposible to delete gisrc file.
+
+    @param gisbase path to GRASS installation
+    @param dbase   path to GRASS database (default: '')
+    @param location location name (default: 'demolocation')
+    @param mapset   mapset within given location (default: 'PERMANENT')
+    @return path to gisrc file
+    """
+    # define PATH
+    os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'bin')
+    os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'scripts')
+    if sys.platform.startswith('win'): # added for winGRASS
+         os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'extralib')
+    # define LD_LIBRARY_PATH
+    if '@LD_LIBRARY_PATH_VAR@' not in os.environ:
+        os.environ['@LD_LIBRARY_PATH_VAR@'] = ''
+    os.environ['@LD_LIBRARY_PATH_VAR@'] += os.pathsep + os.path.join(gisbase, 'lib')
+    
+    os.environ['GIS_LOCK'] = str(os.getpid())
+    
+    # Set PYTHONPATH to find GRASS Python modules
+    path = os.getenv('PYTHONPATH')
+    dir  = os.path.join(gisbase, 'etc', 'python')
+    if path:
+        path = dir + os.pathsep + path
+    else:
+        path = dir
+    os.environ['PYTHONPATH'] = path
+    
+    if not dbase:
+        dbase = gisbase
+    
+    fd, gisrc = tmpfile.mkstemp()
+    os.environ['GISRC'] = gisrc
+    os.write(fd, "GISDBASE: %s\n" % dbase)
+    os.write(fd, "LOCATION_NAME: %s\n" % location)
+    os.write(fd, "MAPSET: %s\n" % mapset)
+    os.close(fd)
+    
+    return gisrc

Copied: grass/trunk/lib/python/script/task.py (from rev 54568, grass/trunk/lib/python/task.py)
===================================================================
--- grass/trunk/lib/python/script/task.py	                        (rev 0)
+++ grass/trunk/lib/python/script/task.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,555 @@
+"""!@package grass.script.task
+
+ at brief GRASS Python scripting module (task)
+
+Get interface description of GRASS commands
+
+Based on gui/wxpython/gui_modules/menuform.py
+
+Usage:
+
+ at code
+from grass.script import task as gtask
+
+gtask.command_info('r.info')
+...
+ at endcode
+
+(C) 2011 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import types
+import string
+try:
+    import xml.etree.ElementTree as etree
+except ImportError:
+    import elementtree.ElementTree as etree # Python <= 2.4
+
+from core import *
+
+class grassTask:
+    """!This class holds the structures needed for filling by the
+    parser
+
+    Parameter blackList is a dictionary with fixed structure, eg.
+
+    @code
+    blackList = {'items' : {'d.legend' : { 'flags' : ['m'],
+                                           'params' : [] }},
+                 'enabled': True}
+    @endcode
+    
+    @param path full path
+    @param blackList hide some options in the GUI (dictionary)
+    """
+    def __init__(self, path = None, blackList = None):
+        self.path = path
+        self.name = _('unknown')
+        self.params = list()
+        self.description = ''
+        self.label = ''
+        self.flags = list()
+        self.keywords = list()
+        self.errorMsg = ''
+        self.firstParam = None
+        if blackList:
+            self.blackList = blackList
+        else:
+            self.blackList = { 'enabled' : False, 'items' : {} }
+        
+        if path is not None:
+            try:
+                processTask(tree = etree.fromstring(get_interface_description(path)),
+                            task = self)
+            except ScriptError, e:
+                self.errorMsg = e.value
+            
+            self.define_first()
+        
+    def define_first(self):
+        """!Define first parameter
+
+        @return name of first parameter
+        """
+        if len(self.params) > 0:
+            self.firstParam = self.params[0]['name']
+        
+        return self.firstParam
+    
+    def get_error_msg(self):
+        """!Get error message ('' for no error)
+        """
+        return self.errorMsg
+    
+    def get_name(self):
+        """!Get task name
+        """
+        if sys.platform == 'win32':
+            name, ext = os.path.splitext(self.name)
+            if ext in ('.py', '.sh'):
+                return name
+            else:
+                return self.name
+        
+        return self.name
+
+    def get_description(self, full = True):
+        """!Get module's description
+
+        @param full True for label + desc
+        """
+        if self.label:
+            if full:
+                return self.label + ' ' + self.description
+            else:
+                return self.label
+        else:
+            return self.description
+
+    def get_keywords(self):
+        """!Get module's keywords
+        """
+        return self.keywords
+    
+    def get_list_params(self, element = 'name'):
+        """!Get list of parameters
+
+        @param element element name
+        """
+        params = []
+        for p in self.params:
+            params.append(p[element])
+        
+        return params
+
+    def get_list_flags(self, element = 'name'):
+        """!Get list of flags
+
+        @param element element name
+        """
+        flags = []
+        for p in self.flags:
+            flags.append(p[element])
+        
+        return flags
+    
+    def get_param(self, value, element = 'name', raiseError = True):
+        """!Find and return a param by name
+
+        @param value param's value
+        @param element element name
+        @param raiseError True for raise on error
+        """
+        try:
+            for p in self.params:
+                val = p[element]
+                if val is None:
+                    continue
+                if type(val) in (types.ListType, types.TupleType):
+                    if value in val:
+                        return p
+                elif type(val) ==  types.StringType:
+                    if p[element][:len(value)] ==  value:
+                        return p
+                else:
+                    if p[element] ==  value:
+                        return p
+        except KeyError:
+            pass
+        
+        if raiseError:
+            raise ValueError, _("Parameter element '%(element)s' not found: '%(value)s'") % \
+                { 'element' : element, 'value' : value }
+        else:
+            return None
+
+    def get_flag(self, aFlag):
+        """!Find and return a flag by name
+
+        Raises ValueError when the flag is not found.
+
+        @param aFlag name of the flag
+        """
+        for f in self.flags:
+            if f['name'] ==  aFlag:
+                return f
+        raise ValueError, _("Flag not found: %s") % aFlag
+
+    def get_cmd_error(self):
+        """!Get error string produced by get_cmd(ignoreErrors = False)
+        
+        @return list of errors
+        """
+        errorList = list()
+        # determine if suppress_required flag is given
+        for f in self.flags:
+            if f['value'] and f['suppress_required']:
+                return errorList
+        
+        for p in self.params:
+            if not p.get('value', '') and p.get('required', False):
+                if not p.get('default', ''):
+                    desc = p.get('label', '')
+                    if not desc:
+                        desc = p['description']
+                    errorList.append(_("Parameter '%(name)s' (%(desc)s) is missing.") % \
+                                         {'name' : p['name'], 'desc' : desc })
+        
+        return errorList
+    
+    def get_cmd(self, ignoreErrors = False, ignoreRequired = False, ignoreDefault = True):
+        """!Produce an array of command name and arguments for feeding
+        into some execve-like command processor.
+
+        @param ignoreErrors True to return whatever has been built so
+        far, even though it would not be a correct command for GRASS
+        @param ignoreRequired True to ignore required flags, otherwise
+        '@<required@>' is shown
+        @param ignoreDefault True to ignore parameters with default values
+        """
+        cmd = [self.get_name()]
+        
+        suppress_required = False
+        for flag in self.flags:
+            if flag['value']:
+                if len(flag['name']) > 1: # e.g. overwrite
+                    cmd +=  [ '--' + flag['name'] ]
+                else:
+                    cmd +=  [ '-' + flag['name'] ]
+                if flag['suppress_required']:
+                    suppress_required = True
+        for p in self.params:
+            if p.get('value', '') ==  '' and p.get('required', False):
+                if p.get('default', '') !=  '':
+                    cmd +=  [ '%s=%s' % (p['name'], p['default']) ]
+                elif ignoreErrors and not suppress_required and not ignoreRequired:
+                    cmd +=  [ '%s=%s' % (p['name'], _('<required>')) ]
+            elif p.get('value', '') ==  '' and p.get('default', '') != '' and not ignoreDefault:
+                cmd +=  [ '%s=%s' % (p['name'], p['default']) ]
+            elif p.get('value', '') !=  '' and \
+                    (p['value'] !=  p.get('default', '') or not ignoreDefault):
+                # output only values that have been set, and different from defaults
+                cmd +=  [ '%s=%s' % (p['name'], p['value']) ]
+        
+        errList = self.get_cmd_error()
+        if ignoreErrors is False and errList:
+            raise ValueError, '\n'.join(errList)
+        
+        return cmd
+
+    def get_options(self):
+        """!Get options
+        """
+        return { 'flags'  : self.flags,
+                 'params' : self.params }
+    
+    def has_required(self):
+        """!Check if command has at least one required paramater
+        """
+        for p in self.params:
+            if p.get('required', False):
+                return True
+        
+        return False
+    
+    def set_param(self, aParam, aValue, element = 'value'):
+        """!Set param value/values.
+        """
+        try:
+            param = self.get_param(aParam)
+        except ValueError:
+            return
+        
+        param[element] = aValue
+
+    def set_flag(self, aFlag, aValue, element = 'value'):
+        """!Enable / disable flag.
+        """
+        try:
+            param = self.get_flag(aFlag)
+        except ValueError:
+            return
+        
+        param[element] = aValue
+
+    def set_options(self, opts):
+        """!Set flags and parameters
+
+        @param opts list of flags and parameters"""
+        for opt in opts:
+            if opt[0] ==  '-': # flag
+                self.set_flag(opt.lstrip('-'), True)
+            else: # parameter
+                key, value = opt.split('=', 1)
+                self.set_param(key, value)
+        
+class processTask:
+    """!A ElementTree handler for the --interface-description output,
+    as defined in grass-interface.dtd. Extend or modify this and the
+    DTD if the XML output of GRASS' parser is extended or modified.
+
+    @param tree root tree node
+    @param task grassTask instance or None
+    @param blackList list of flags/params to hide
+    
+    @return grassTask instance
+    """
+    def __init__(self, tree, task = None, blackList = None):
+        if task:
+            self.task = task
+        else:
+            self.task = grassTask()
+        if blackList:
+            self.task.blackList = blackList
+        
+        self.root = tree
+        
+        self._process_module()
+        self._process_params()
+        self._process_flags()
+        self.task.define_first()
+        
+    def _process_module(self):
+        """!Process module description
+        """
+        self.task.name = self.root.get('name', default = 'unknown')
+        
+        # keywords
+        for keyword in self._get_node_text(self.root, 'keywords').split(','):
+            self.task.keywords.append(keyword.strip())
+        
+        self.task.label       = self._get_node_text(self.root, 'label')
+        self.task.description = self._get_node_text(self.root, 'description')
+        
+    def _process_params(self):
+        """!Process parameters
+        """
+        for p in self.root.findall('parameter'):
+            # gisprompt
+            node_gisprompt = p.find('gisprompt')
+            gisprompt = False
+            age = element = prompt = None
+            if node_gisprompt is not None:
+                gisprompt = True
+                age     = node_gisprompt.get('age', '')
+                element = node_gisprompt.get('element', '')
+                prompt  = node_gisprompt.get('prompt', '')
+            
+            # value(s)
+            values = []
+            values_desc = []
+            node_values = p.find('values')
+            if node_values is not None:
+                for pv in node_values.findall('value'):
+                    values.append(self._get_node_text(pv, 'name'))
+                    desc = self._get_node_text(pv, 'description')
+                    if desc:
+                        values_desc.append(desc)
+            
+            # keydesc
+            key_desc = []
+            node_key_desc = p.find('keydesc')
+            if node_key_desc is not None:
+                for ki in node_key_desc.findall('item'):
+                    key_desc.append(ki.text)
+            
+            if p.get('multiple', 'no') ==  'yes':
+                multiple = True
+            else:
+                multiple = False
+            if p.get('required', 'no') ==  'yes':
+                required = True
+            else:
+                required = False
+            
+            if self.task.blackList['enabled'] and \
+                    self.task.name in self.task.blackList['items'] and \
+                    p.get('name') in self.task.blackList['items'][self.task.name].get('params', []):
+                hidden = True
+            else:
+                hidden = False
+            
+            self.task.params.append( {
+                "name"           : p.get('name'),
+                "type"           : p.get('type'),
+                "required"       : required,
+                "multiple"       : multiple,
+                "label"          : self._get_node_text(p, 'label'),
+                "description"    : self._get_node_text(p, 'description'),
+                'gisprompt'      : gisprompt,
+                'age'            : age,
+                'element'        : element,
+                'prompt'         : prompt,
+                "guisection"     : self._get_node_text(p, 'guisection'),
+                "guidependency"  : self._get_node_text(p, 'guidependency'),
+                "default"        : self._get_node_text(p, 'default'),
+                "values"         : values,
+                "values_desc"    : values_desc,
+                "value"          : '',
+                "key_desc"       : key_desc,
+                "hidden"         : hidden
+                })
+            
+    def _process_flags(self):
+        """!Process flags
+        """
+        for p in self.root.findall('flag'):
+            if self.task.blackList['enabled'] and \
+                    self.task.name in self.task.blackList['items'] and \
+                    p.get('name') in self.task.blackList['items'][self.task.name].get('flags', []):
+                hidden = True
+            else:
+                hidden = False
+            
+            if p.find('suppress_required') is not None:
+                suppress_required = True
+            else:
+                suppress_required = False
+            
+            self.task.flags.append( {
+                    "name"              : p.get('name'),
+                    "label"             : self._get_node_text(p, 'label'),
+                    "description"       : self._get_node_text(p, 'description'),
+                    "guisection"        : self._get_node_text(p, 'guisection'),
+                    "suppress_required" : suppress_required,
+                    "value"             : False,
+                    "hidden"            : hidden
+                    } )
+        
+    def _get_node_text(self, node, tag, default = ''):
+        """!Get node text"""
+        p = node.find(tag)
+        if p is not None:
+            return string.join(string.split(p.text), ' ')
+        
+        return default
+    
+    def get_task(self):
+        """!Get grassTask instance"""
+        return self.task
+
+def get_interface_description(cmd):
+    """!Returns the XML description for the GRASS cmd.
+
+    The DTD must be located in $GISBASE/etc/grass-interface.dtd,
+    otherwise the parser will not succeed.
+
+    @param cmd command (name of GRASS module)
+    """
+    try:
+	p = Popen([cmd, '--interface-description'], stdout = PIPE,
+						    stderr = PIPE)
+        cmdout, cmderr = p.communicate()
+        
+        # TODO: replace ugly hack bellow
+        if not cmdout and sys.platform == 'win32':
+            if os.path.splitext(cmd)[1] == '':
+                cmd += '.py'
+            
+            os.chdir(os.path.join(os.getenv('GISBASE'), 'scripts'))
+	    p = Popen([sys.executable, cmd, '--interface-description'],
+		      stdout = PIPE, stderr = PIPE)
+            cmdout, cmderr = p.communicate()
+        
+        if p.returncode != 0:
+            raise ScriptError, _("Unable to fetch interface description for command '%(cmd)s'."
+                                 "\n\nDetails: %(det)s") % { 'cmd' : cmd, 'det' : decode(cmderr) }
+    
+    except OSError, e:
+        raise ScriptError, _("Unable to fetch interface description for command '%(cmd)s'."
+                             "\n\nDetails: %(det)s") % { 'cmd' : cmd, 'det' : e }
+    
+    # if cmderr and cmderr[:7] != 'WARNING':
+    # raise ScriptError, _("Unable to fetch interface description for command '%(cmd)s'."
+    # "\n\nDetails: %(det)s") % { 'cmd': cmd, 'det' : decode(cmderr) }
+    
+    return cmdout.replace('grass-interface.dtd', os.path.join(os.getenv('GISBASE'), 'etc', 'grass-interface.dtd'))
+
+def parse_interface(name, parser = processTask, blackList = None):
+    """!Parse interface of given GRASS module
+    
+    @param name name of GRASS module to be parsed
+    """
+    enc = locale.getdefaultlocale()[1]
+    if enc and enc.lower() == "cp932":
+        p = re.compile('encoding="' + enc + '"', re.IGNORECASE)
+        tree = etree.fromstring(p.sub('encoding="utf-8"',
+                                      get_interface_description(name).decode(enc).encode("utf-8")))
+    else:
+        tree = etree.fromstring(get_interface_description(name))
+    
+    return parser(tree, blackList = blackList).get_task()
+
+def command_info(cmd):
+    """!Returns meta information for any GRASS command as dictionary
+    with entries for description, keywords, usage, flags, and
+    parameters, e.g.
+    
+    @code
+    >>> gtask.command_info('g.tempfile')
+    
+    {'keywords': ['general', 'map management'],
+     'params': [{'gisprompt': False, 'multiple': False, 'name': 'pid', 'guidependency': '',
+                'default': '', 'age': None, 'required': True, 'value': '',
+                'label': '', 'guisection': '', 'key_desc': [], 'values': [], 'values_desc': [],
+                'prompt': None, 'hidden': False, 'element': None, 'type': 'integer',
+                'description': 'Process id to use when naming the tempfile'}],
+     'flags': [{'description': 'Verbose module output', 'value': False, 'label': '', 'guisection': '',
+                'suppress_required': False, 'hidden': False, 'name': 'verbose'}, {'description': 'Quiet module output',
+                'value': False, 'label': '', 'guisection': '', 'suppress_required': False, 'hidden': False, 'name': 'quiet'}],
+     'description': 'Creates a temporary file and prints the file name.',
+     'usage': 'g.tempfile pid=integer [--verbose] [--quiet]'
+    }
+
+    >>> gtask.command_info('v.buffer')['keywords']
+    
+    ['vector', 'geometry', 'buffer']
+    @endcode
+    """
+    task = parse_interface(cmd)
+    cmdinfo = {}
+    
+    cmdinfo['description'] = task.get_description()
+    cmdinfo['keywords']    = task.get_keywords()
+    cmdinfo['flags']       = flags = task.get_options()['flags']
+    cmdinfo['params']      = params = task.get_options()['params']
+    
+    usage = task.get_name()
+    flags_short = list()
+    flags_long  = list()
+    for f in flags:
+        fname = f.get('name', 'unknown')
+        if len(fname) > 1:
+            flags_long.append(fname)
+        else:
+            flags_short.append(fname)
+    
+    if len(flags_short) > 1:
+        usage += ' [-' + ''.join(flags_short) + ']'
+    
+    for p in params:
+        ptype = ','.join(p.get('key_desc', []))
+        if not ptype:
+            ptype = p.get('type', '')
+        req =  p.get('required', False)
+        if not req:
+           usage += ' ['
+        else:
+            usage += ' '
+        usage += p['name'] + '=' + ptype
+        if p.get('multiple', False):
+            usage += '[,' + ptype + ',...]'
+        if not req:
+            usage += ']'
+        
+    for key in flags_long:
+        usage += ' [--' + key + ']'
+    
+    cmdinfo['usage'] = usage
+    
+    return cmdinfo

Copied: grass/trunk/lib/python/script/vector.py (from rev 54568, grass/trunk/lib/python/vector.py)
===================================================================
--- grass/trunk/lib/python/script/vector.py	                        (rev 0)
+++ grass/trunk/lib/python/script/vector.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -0,0 +1,411 @@
+"""!@package grass.script.vector
+
+ at brief GRASS Python scripting module (vector functions)
+
+Vector related functions to be used in Python scripts.
+
+Usage:
+
+ at code
+from grass.script import vector as grass
+
+grass.vector_db(map)
+...
+ at endcode
+
+(C) 2008-2010 by the GRASS Development Team
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Glynn Clements
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+import types
+import copy
+import __builtin__
+
+from core import *
+
+# run "v.db.connect -g ..." and parse output
+
+def vector_db(map, **args):
+    """!Return the database connection details for a vector map
+    (interface to `v.db.connect -g'). Example:
+    
+    \code
+    >>> grass.vector_db('lakes')
+    {1: {'layer': 1, 'name': '',
+    'database': '/home/martin/grassdata/nc_spm_08/PERMANENT/dbf/',
+    'driver': 'dbf', 'key': 'cat', 'table': 'lakes'}}
+    \endcode
+    
+    @param map vector map
+    @param args other v.db.connect's arguments
+    
+    @return dictionary
+    """
+    s = read_command('v.db.connect', quiet = True, flags = 'g', map = map, sep = ';', **args)
+    result = {}
+    
+    for l in s.splitlines():
+	f = l.split(';')
+	if len(f) != 5:
+	    continue
+        
+        if '/' in f[0]:
+            f1 = f[0].split('/')
+            layer = f1[0]
+            name = f1[1]
+        else:
+            layer = f[0]
+            name = ''
+            
+	result[int(layer)] = {
+            'layer'    : int(layer),
+            'name'     : name,
+            'table'    : f[1],
+            'key'      : f[2],
+            'database' : f[3],
+            'driver'   : f[4] }
+    
+    return result
+
+def vector_layer_db(map, layer):
+    """!Return the database connection details for a vector map layer.
+    If db connection for given layer is not defined, fatal() is called.
+    
+    @param map map name
+    @param layer layer number
+    
+    @return parsed output
+    """
+    try:
+        f = vector_db(map)[int(layer)]
+    except KeyError:
+	fatal(_("Database connection not defined for layer %s") % layer)
+
+    return f
+
+# run "v.info -c ..." and parse output
+
+def vector_columns(map, layer = None, getDict = True, **args):
+    """!Return a dictionary (or a list) of the columns for the
+    database table connected to a vector map (interface to `v.info
+    -c').
+
+    @code
+    >>> vector_columns(urbanarea, getDict = True)
+    {'UA_TYPE': {'index': 4, 'type': 'CHARACTER'}, 'UA': {'index': 2, 'type': 'CHARACTER'}, 'NAME': {'index': 3, 'type': 'CHARACTER'}, 'OBJECTID': {'index': 1, 'type': 'INTEGER'}, 'cat': {'index': 0, 'type': 'INTEGER'}}
+
+    >>> vector_columns(urbanarea, getDict = False)
+    ['cat', 'OBJECTID', 'UA', 'NAME', 'UA_TYPE']
+    @endcode
+    
+    @param map map name
+    @param layer layer number or name (None for all layers)
+    @param getDict True to return dictionary of columns otherwise list of column names is returned
+    @param args (v.info's arguments)
+    
+    @return dictionary/list of columns
+    """
+    s = read_command('v.info', flags = 'c', map = map, layer = layer, quiet = True, **args)
+    if getDict:
+        result = dict()
+    else:
+        result = list()
+    i = 0
+    for line in s.splitlines():
+	ctype, cname = line.split('|')
+        if getDict:
+            result[cname] = { 'type' : ctype,
+                              'index' : i }
+        else:
+            result.append(cname)
+        i+=1
+    
+    return result
+
+# add vector history
+
+def vector_history(map):
+    """!Set the command history for a vector map to the command used to
+    invoke the script (interface to `v.support').
+
+    @param map mapname
+
+    @return v.support output
+    """
+    run_command('v.support', map = map, cmdhist = os.environ['CMDLINE'])
+
+# run "v.info -t" and parse output
+
+def vector_info_topo(map):
+    """!Return information about a vector map (interface to `v.info
+    -t'). Example:
+
+    \code
+    >>> grass.vector_info_topo('lakes')
+    {'kernels': 0, 'lines': 0, 'centroids': 15279,
+    'boundaries': 27764, 'points': 0, 'faces': 0,
+    'primitives': 43043, 'islands': 7470, 'nodes': 35234, 'map3d': False, 'areas': 15279}
+    \endcode
+    
+    @param map map name
+
+    @return parsed output
+    """
+    s = read_command('v.info', flags = 't', map = map)
+    ret = parse_key_val(s, val_type = int)
+    if 'map3d' in ret:
+        ret['map3d'] = bool(ret['map3d'])
+    
+    return ret
+
+
+# run "v.info -get ..." and parse output
+
+def vector_info(map):
+    """!Return information about a vector map (interface to
+    `v.info'). Example:
+
+    \code
+    >>> grass.vector_info('random_points')
+    {'comment': '', 'projection': 'x,y', 'creator': 'soeren', 'holes': 0, 
+     'primitives': 20, 'kernels': 0, 'scale': '1:1', 'title': '', 
+     'west': 0.046125489999999998, 'top': 2376.133159, 'boundaries': 0, 
+     'location': 'XYLocation', 'nodes': 0, 'east': 0.97305646000000001, 
+     'source_date': 'Mon Aug 29 10:55:57 2011', 'north': 0.9589993, 
+     'format': 'native', 'faces': 0, 'centroids': 0, 
+     'digitization_threshold': '0.000000', 'islands': 0, 'level': 2, 
+     'mapset': 'test', 'areas': 0, 'name': 'random_points', 
+     'database': '/home/soeren/grassdata', 'bottom': 22.186596999999999, 
+     'lines': 0, 'points': 20, 'map3d': True, 'volumes': 0, 'num_dblinks': 0, 
+     'organization': '', 'south': 0.066047099999999997}
+    
+    \endcode
+    @param map map name
+    
+    @return parsed vector info
+    """
+
+    s = read_command('v.info', flags = 'get', map = map)
+    
+    kv = parse_key_val(s)
+    for k in ['north', 'south', 'east', 'west', 'top', 'bottom']:
+	kv[k] = float(kv[k])
+    for k in ['level', 'num_dblinks']:
+	kv[k] = int(kv[k])
+    for k in ['nodes', 'points', 'lines', 'boundaries', 'centroids', 'areas', 'islands', 'primitives']:
+	kv[k] = int(kv[k])
+    if 'map3d' in kv:
+        kv['map3d'] = bool(int(kv['map3d']))
+        if kv['map3d']:
+            for k in ['faces', 'kernels', 'volumes', 'holes']:
+                kv[k] = int(kv[k])
+
+    return kv
+
+
+# interface for v.db.select
+
+def vector_db_select(map, layer = 1, **kwargs):
+    """!Get attribute data of selected vector map layer.
+
+    Function returns list of columns and dictionary of values ordered by
+    key column value. Example:
+
+    \code
+    >>> print grass.vector_db_select('lakes')['columns']
+    ['cat', 'AREA', 'PERIMETER', 'FULL_HYDRO', 'FULL_HYDR2', 'FTYPE', 'FCODE', 'NAME']
+    >>> print grass.vector_db_select('lakes')['values'][3]
+    ['3', '19512.86146', '708.44683', '4', '55652', 'LAKE/POND', '39000', '']
+    >>> print grass.vector_db_select('lakes', columns = 'FTYPE')['values'][3]
+    ['LAKE/POND']
+    \endcode
+
+    @param map map name
+    @param layer layer number
+    @param kwargs v.db.select options
+
+    @return dictionary ('columns' and 'values')
+    """
+    try:
+        key = vector_db(map = map)[layer]['key']
+    except KeyError:
+        error(_('Missing layer %(layer)d in vector map <%(map)s>') % \
+                  { 'layer' : layer, 'map' : map })
+        return { 'columns' : [], 'values' : {} }
+        
+    if 'columns' in kwargs:
+        if key not in kwargs['columns'].split(','):
+            # add key column if missing
+            debug("Adding key column to the output")
+            kwargs['columns'] += ',' + key
+    
+    ret = read_command('v.db.select',
+                       map = map,
+                       layer = layer,
+                       **kwargs)
+    
+    if not ret:
+        error(_('vector_db_select() failed'))
+        return { 'columns' : [], 'values' : {} }
+    
+    columns = []
+    values = {}
+    for line in ret.splitlines():
+        if not columns:
+            columns = line.split('|')
+            key_index = columns.index(key)
+            continue
+        
+        value = line.split('|')
+        key_value = int(value[key_index])
+        values[key_value] = line.split('|')
+    
+    return { 'columns' : columns,
+             'values' : values }
+
+# interface to v.what
+def vector_what(map, coord, distance = 0.0, ttype = None):
+    """!Query vector map at given locations
+    
+    To query one vector map at one location
+    @code
+    print grass.vector_what(map = 'archsites', coord = (595743, 4925281), distance = 250)
+
+    [{'Category': 8, 'Map': 'archsites', 'Layer': 1, 'Key_column': 'cat',
+      'Database': '/home/martin/grassdata/spearfish60/PERMANENT/dbf/',
+      'Mapset': 'PERMANENT', 'Driver': 'dbf',
+      'Attributes': {'str1': 'No_Name', 'cat': '8'},
+      'Table': 'archsites', 'Type': 'Point', 'Id': 8}]
+    @endcode
+
+    To query one vector map with multiple layers (no additional parameters required)
+    @code
+    for q in grass.vector_what(map = 'some_map', coord = (596532.357143,4920486.21429), distance = 100.0):
+        print q['Map'], q['Layer'], q['Attributes']
+
+    new_bug_sites 1 {'str1': 'Beetle_site', 'GRASSRGB': '', 'cat': '80'}
+    new_bug_sites 2 {'cat': '80'}
+    @endcode
+
+    To query more vector maps at one location
+    @code
+    for q in grass.vector_what(map = ('archsites', 'roads'), coord = (595743, 4925281),
+                               distance = 250):
+        print q['Map'], q['Attributes']
+                            
+    archsites {'str1': 'No_Name', 'cat': '8'}
+    roads {'label': 'interstate', 'cat': '1'}
+    @endcode
+
+    To query one vector map at more locations
+    @code
+    for q in grass.vector_what(map = 'archsites', coord = [(595743, 4925281), (597950, 4918898)],
+                               distance = 250):
+        print q['Map'], q['Attributes']
+
+    archsites {'str1': 'No_Name', 'cat': '8'}
+    archsites {'str1': 'Bob_Miller', 'cat': '22'}
+    @endcode
+
+    @param map vector map(s) to query given as string or list/tuple
+    @param coord coordinates of query given as tuple (easting, northing) or list of tuples
+    @param distance query threshold distance (in map units)
+    @param ttype list of topology types (default of v.what are point, line, area, face)
+
+    @return parsed list
+    """
+    if "LC_ALL" in os.environ:
+        locale = os.environ["LC_ALL"]
+        os.environ["LC_ALL"] = "C"
+
+    if type(map) in (types.StringType, types.UnicodeType):
+        map_list = [map]
+    else:
+        map_list = map
+    
+    layer_list = ['-1'] * len(map_list)
+    
+    coord_list = list()
+    if type(coord) is types.TupleType:
+        coord_list.append('%f,%f' % (coord[0], coord[1]))
+    else:
+        for e, n in coord:
+            coord_list.append('%f,%f' % (e, n))
+    
+    cmdParams = dict(quiet      = True,
+                     flags      = 'ag',
+                     map        = ','.join(map_list),
+                     layer      = ','.join(layer_list),
+                     coordinates = ','.join(coord_list),
+                     distance   = float(distance))
+    if ttype:
+        cmdParams['type'] = ','.join(ttype)
+
+    ret = read_command('v.what',
+                       **cmdParams)
+    
+    if "LC_ALL" in os.environ:
+        os.environ["LC_ALL"] = locale
+        
+    data = list()
+    if not ret:
+        return data
+    
+    dict_attrb = None
+    dict_map = None
+    dict_layer = None
+    attr_pseudo_key = 'Attributes'
+    for item in ret.splitlines():
+        try:
+            key, value = __builtin__.map(lambda x: x.strip(), item.split('=', 1))
+        except ValueError:
+            continue
+        if key in ('East', 'North'):
+            continue
+        
+        if key == 'Map':
+            # attach the last one from the previous map
+            if dict_layer is not None:
+                dict_main = copy.copy(dict_map)
+                dict_main.update(dict_layer)
+                data.append(dict_main)
+            dict_map  = { key : value }
+            dict_layer = None
+            dict_attrb = None
+        elif key == 'Layer':
+            # attach the last the previous Layer
+            if dict_layer is not None:
+                dict_main = copy.copy(dict_map)
+                dict_main.update(dict_layer)
+                data.append(dict_main)
+            dict_layer = { key: int(value) }
+            dict_attrb = None
+        elif key == 'Key_column':
+            dict_layer[key] = value
+            dict_attrb = dict()
+            dict_layer[attr_pseudo_key] = dict_attrb
+        elif dict_attrb is not None:
+            dict_attrb[key] = value
+        elif dict_layer is not None:
+            if key == 'Category':
+                dict_layer[key] = int(value)
+            else:
+                dict_layer[key] = value
+        else:
+            dict_map[key] = value
+            # TODO: there are some keys which has non-string values
+            # examples: Sq_Meters, Hectares, Acres, Sq_Miles
+    
+    # attach the last one
+    if dict_layer is not None:
+        dict_main = copy.copy(dict_map)
+        dict_main.update(dict_layer)
+        data.append(dict_main)
+    
+    return data

Deleted: grass/trunk/lib/python/setup.py.sed
===================================================================
--- grass/trunk/lib/python/setup.py.sed	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/setup.py.sed	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,71 +0,0 @@
-"""!@package grass.script.setup
-
- at brief GRASS Python scripting module (setup)
-
-Setup functions to be used in Python scripts.
-
-Usage:
-
- at code
-from grass.script import setup as grass
-
-grass.init()
-...
- at endcode
-
-(C) 2010-2012 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Martin Landa <landa.martin gmail.com>
-"""
-
-import os
-import sys
-import tempfile as tmpfile
-
-def init(gisbase, dbase = '', location = 'demolocation', mapset = 'PERMANENT'):
-    """!Initialize system variables to run scripts without starting
-    GRASS explicitly.
-
-    User is resposible to delete gisrc file.
-
-    @param gisbase path to GRASS installation
-    @param dbase   path to GRASS database (default: '')
-    @param location location name (default: 'demolocation')
-    @param mapset   mapset within given location (default: 'PERMANENT')
-    @return path to gisrc file
-    """
-    # define PATH
-    os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'bin')
-    os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'scripts')
-    if sys.platform.startswith('win'): # added for winGRASS
-         os.environ['PATH'] += os.pathsep + os.path.join(gisbase, 'extralib')
-    # define LD_LIBRARY_PATH
-    if '@LD_LIBRARY_PATH_VAR@' not in os.environ:
-        os.environ['@LD_LIBRARY_PATH_VAR@'] = ''
-    os.environ['@LD_LIBRARY_PATH_VAR@'] += os.pathsep + os.path.join(gisbase, 'lib')
-    
-    os.environ['GIS_LOCK'] = str(os.getpid())
-    
-    # Set PYTHONPATH to find GRASS Python modules
-    path = os.getenv('PYTHONPATH')
-    dir  = os.path.join(gisbase, 'etc', 'python')
-    if path:
-        path = dir + os.pathsep + path
-    else:
-        path = dir
-    os.environ['PYTHONPATH'] = path
-    
-    if not dbase:
-        dbase = gisbase
-    
-    fd, gisrc = tmpfile.mkstemp()
-    os.environ['GISRC'] = gisrc
-    os.write(fd, "GISDBASE: %s\n" % dbase)
-    os.write(fd, "LOCATION_NAME: %s\n" % location)
-    os.write(fd, "MAPSET: %s\n" % mapset)
-    os.close(fd)
-    
-    return gisrc

Deleted: grass/trunk/lib/python/task.py
===================================================================
--- grass/trunk/lib/python/task.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/task.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,555 +0,0 @@
-"""!@package grass.script.task
-
- at brief GRASS Python scripting module (task)
-
-Get interface description of GRASS commands
-
-Based on gui/wxpython/gui_modules/menuform.py
-
-Usage:
-
- at code
-from grass.script import task as gtask
-
-gtask.command_info('r.info')
-...
- at endcode
-
-(C) 2011 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Martin Landa <landa.martin gmail.com>
-"""
-
-import types
-import string
-try:
-    import xml.etree.ElementTree as etree
-except ImportError:
-    import elementtree.ElementTree as etree # Python <= 2.4
-
-from core import *
-
-class grassTask:
-    """!This class holds the structures needed for filling by the
-    parser
-
-    Parameter blackList is a dictionary with fixed structure, eg.
-
-    @code
-    blackList = {'items' : {'d.legend' : { 'flags' : ['m'],
-                                           'params' : [] }},
-                 'enabled': True}
-    @endcode
-    
-    @param path full path
-    @param blackList hide some options in the GUI (dictionary)
-    """
-    def __init__(self, path = None, blackList = None):
-        self.path = path
-        self.name = _('unknown')
-        self.params = list()
-        self.description = ''
-        self.label = ''
-        self.flags = list()
-        self.keywords = list()
-        self.errorMsg = ''
-        self.firstParam = None
-        if blackList:
-            self.blackList = blackList
-        else:
-            self.blackList = { 'enabled' : False, 'items' : {} }
-        
-        if path is not None:
-            try:
-                processTask(tree = etree.fromstring(get_interface_description(path)),
-                            task = self)
-            except ScriptError, e:
-                self.errorMsg = e.value
-            
-            self.define_first()
-        
-    def define_first(self):
-        """!Define first parameter
-
-        @return name of first parameter
-        """
-        if len(self.params) > 0:
-            self.firstParam = self.params[0]['name']
-        
-        return self.firstParam
-    
-    def get_error_msg(self):
-        """!Get error message ('' for no error)
-        """
-        return self.errorMsg
-    
-    def get_name(self):
-        """!Get task name
-        """
-        if sys.platform == 'win32':
-            name, ext = os.path.splitext(self.name)
-            if ext in ('.py', '.sh'):
-                return name
-            else:
-                return self.name
-        
-        return self.name
-
-    def get_description(self, full = True):
-        """!Get module's description
-
-        @param full True for label + desc
-        """
-        if self.label:
-            if full:
-                return self.label + ' ' + self.description
-            else:
-                return self.label
-        else:
-            return self.description
-
-    def get_keywords(self):
-        """!Get module's keywords
-        """
-        return self.keywords
-    
-    def get_list_params(self, element = 'name'):
-        """!Get list of parameters
-
-        @param element element name
-        """
-        params = []
-        for p in self.params:
-            params.append(p[element])
-        
-        return params
-
-    def get_list_flags(self, element = 'name'):
-        """!Get list of flags
-
-        @param element element name
-        """
-        flags = []
-        for p in self.flags:
-            flags.append(p[element])
-        
-        return flags
-    
-    def get_param(self, value, element = 'name', raiseError = True):
-        """!Find and return a param by name
-
-        @param value param's value
-        @param element element name
-        @param raiseError True for raise on error
-        """
-        try:
-            for p in self.params:
-                val = p[element]
-                if val is None:
-                    continue
-                if type(val) in (types.ListType, types.TupleType):
-                    if value in val:
-                        return p
-                elif type(val) ==  types.StringType:
-                    if p[element][:len(value)] ==  value:
-                        return p
-                else:
-                    if p[element] ==  value:
-                        return p
-        except KeyError:
-            pass
-        
-        if raiseError:
-            raise ValueError, _("Parameter element '%(element)s' not found: '%(value)s'") % \
-                { 'element' : element, 'value' : value }
-        else:
-            return None
-
-    def get_flag(self, aFlag):
-        """!Find and return a flag by name
-
-        Raises ValueError when the flag is not found.
-
-        @param aFlag name of the flag
-        """
-        for f in self.flags:
-            if f['name'] ==  aFlag:
-                return f
-        raise ValueError, _("Flag not found: %s") % aFlag
-
-    def get_cmd_error(self):
-        """!Get error string produced by get_cmd(ignoreErrors = False)
-        
-        @return list of errors
-        """
-        errorList = list()
-        # determine if suppress_required flag is given
-        for f in self.flags:
-            if f['value'] and f['suppress_required']:
-                return errorList
-        
-        for p in self.params:
-            if not p.get('value', '') and p.get('required', False):
-                if not p.get('default', ''):
-                    desc = p.get('label', '')
-                    if not desc:
-                        desc = p['description']
-                    errorList.append(_("Parameter '%(name)s' (%(desc)s) is missing.") % \
-                                         {'name' : p['name'], 'desc' : desc })
-        
-        return errorList
-    
-    def get_cmd(self, ignoreErrors = False, ignoreRequired = False, ignoreDefault = True):
-        """!Produce an array of command name and arguments for feeding
-        into some execve-like command processor.
-
-        @param ignoreErrors True to return whatever has been built so
-        far, even though it would not be a correct command for GRASS
-        @param ignoreRequired True to ignore required flags, otherwise
-        '@<required@>' is shown
-        @param ignoreDefault True to ignore parameters with default values
-        """
-        cmd = [self.get_name()]
-        
-        suppress_required = False
-        for flag in self.flags:
-            if flag['value']:
-                if len(flag['name']) > 1: # e.g. overwrite
-                    cmd +=  [ '--' + flag['name'] ]
-                else:
-                    cmd +=  [ '-' + flag['name'] ]
-                if flag['suppress_required']:
-                    suppress_required = True
-        for p in self.params:
-            if p.get('value', '') ==  '' and p.get('required', False):
-                if p.get('default', '') !=  '':
-                    cmd +=  [ '%s=%s' % (p['name'], p['default']) ]
-                elif ignoreErrors and not suppress_required and not ignoreRequired:
-                    cmd +=  [ '%s=%s' % (p['name'], _('<required>')) ]
-            elif p.get('value', '') ==  '' and p.get('default', '') != '' and not ignoreDefault:
-                cmd +=  [ '%s=%s' % (p['name'], p['default']) ]
-            elif p.get('value', '') !=  '' and \
-                    (p['value'] !=  p.get('default', '') or not ignoreDefault):
-                # output only values that have been set, and different from defaults
-                cmd +=  [ '%s=%s' % (p['name'], p['value']) ]
-        
-        errList = self.get_cmd_error()
-        if ignoreErrors is False and errList:
-            raise ValueError, '\n'.join(errList)
-        
-        return cmd
-
-    def get_options(self):
-        """!Get options
-        """
-        return { 'flags'  : self.flags,
-                 'params' : self.params }
-    
-    def has_required(self):
-        """!Check if command has at least one required paramater
-        """
-        for p in self.params:
-            if p.get('required', False):
-                return True
-        
-        return False
-    
-    def set_param(self, aParam, aValue, element = 'value'):
-        """!Set param value/values.
-        """
-        try:
-            param = self.get_param(aParam)
-        except ValueError:
-            return
-        
-        param[element] = aValue
-
-    def set_flag(self, aFlag, aValue, element = 'value'):
-        """!Enable / disable flag.
-        """
-        try:
-            param = self.get_flag(aFlag)
-        except ValueError:
-            return
-        
-        param[element] = aValue
-
-    def set_options(self, opts):
-        """!Set flags and parameters
-
-        @param opts list of flags and parameters"""
-        for opt in opts:
-            if opt[0] ==  '-': # flag
-                self.set_flag(opt.lstrip('-'), True)
-            else: # parameter
-                key, value = opt.split('=', 1)
-                self.set_param(key, value)
-        
-class processTask:
-    """!A ElementTree handler for the --interface-description output,
-    as defined in grass-interface.dtd. Extend or modify this and the
-    DTD if the XML output of GRASS' parser is extended or modified.
-
-    @param tree root tree node
-    @param task grassTask instance or None
-    @param blackList list of flags/params to hide
-    
-    @return grassTask instance
-    """
-    def __init__(self, tree, task = None, blackList = None):
-        if task:
-            self.task = task
-        else:
-            self.task = grassTask()
-        if blackList:
-            self.task.blackList = blackList
-        
-        self.root = tree
-        
-        self._process_module()
-        self._process_params()
-        self._process_flags()
-        self.task.define_first()
-        
-    def _process_module(self):
-        """!Process module description
-        """
-        self.task.name = self.root.get('name', default = 'unknown')
-        
-        # keywords
-        for keyword in self._get_node_text(self.root, 'keywords').split(','):
-            self.task.keywords.append(keyword.strip())
-        
-        self.task.label       = self._get_node_text(self.root, 'label')
-        self.task.description = self._get_node_text(self.root, 'description')
-        
-    def _process_params(self):
-        """!Process parameters
-        """
-        for p in self.root.findall('parameter'):
-            # gisprompt
-            node_gisprompt = p.find('gisprompt')
-            gisprompt = False
-            age = element = prompt = None
-            if node_gisprompt is not None:
-                gisprompt = True
-                age     = node_gisprompt.get('age', '')
-                element = node_gisprompt.get('element', '')
-                prompt  = node_gisprompt.get('prompt', '')
-            
-            # value(s)
-            values = []
-            values_desc = []
-            node_values = p.find('values')
-            if node_values is not None:
-                for pv in node_values.findall('value'):
-                    values.append(self._get_node_text(pv, 'name'))
-                    desc = self._get_node_text(pv, 'description')
-                    if desc:
-                        values_desc.append(desc)
-            
-            # keydesc
-            key_desc = []
-            node_key_desc = p.find('keydesc')
-            if node_key_desc is not None:
-                for ki in node_key_desc.findall('item'):
-                    key_desc.append(ki.text)
-            
-            if p.get('multiple', 'no') ==  'yes':
-                multiple = True
-            else:
-                multiple = False
-            if p.get('required', 'no') ==  'yes':
-                required = True
-            else:
-                required = False
-            
-            if self.task.blackList['enabled'] and \
-                    self.task.name in self.task.blackList['items'] and \
-                    p.get('name') in self.task.blackList['items'][self.task.name].get('params', []):
-                hidden = True
-            else:
-                hidden = False
-            
-            self.task.params.append( {
-                "name"           : p.get('name'),
-                "type"           : p.get('type'),
-                "required"       : required,
-                "multiple"       : multiple,
-                "label"          : self._get_node_text(p, 'label'),
-                "description"    : self._get_node_text(p, 'description'),
-                'gisprompt'      : gisprompt,
-                'age'            : age,
-                'element'        : element,
-                'prompt'         : prompt,
-                "guisection"     : self._get_node_text(p, 'guisection'),
-                "guidependency"  : self._get_node_text(p, 'guidependency'),
-                "default"        : self._get_node_text(p, 'default'),
-                "values"         : values,
-                "values_desc"    : values_desc,
-                "value"          : '',
-                "key_desc"       : key_desc,
-                "hidden"         : hidden
-                })
-            
-    def _process_flags(self):
-        """!Process flags
-        """
-        for p in self.root.findall('flag'):
-            if self.task.blackList['enabled'] and \
-                    self.task.name in self.task.blackList['items'] and \
-                    p.get('name') in self.task.blackList['items'][self.task.name].get('flags', []):
-                hidden = True
-            else:
-                hidden = False
-            
-            if p.find('suppress_required') is not None:
-                suppress_required = True
-            else:
-                suppress_required = False
-            
-            self.task.flags.append( {
-                    "name"              : p.get('name'),
-                    "label"             : self._get_node_text(p, 'label'),
-                    "description"       : self._get_node_text(p, 'description'),
-                    "guisection"        : self._get_node_text(p, 'guisection'),
-                    "suppress_required" : suppress_required,
-                    "value"             : False,
-                    "hidden"            : hidden
-                    } )
-        
-    def _get_node_text(self, node, tag, default = ''):
-        """!Get node text"""
-        p = node.find(tag)
-        if p is not None:
-            return string.join(string.split(p.text), ' ')
-        
-        return default
-    
-    def get_task(self):
-        """!Get grassTask instance"""
-        return self.task
-
-def get_interface_description(cmd):
-    """!Returns the XML description for the GRASS cmd.
-
-    The DTD must be located in $GISBASE/etc/grass-interface.dtd,
-    otherwise the parser will not succeed.
-
-    @param cmd command (name of GRASS module)
-    """
-    try:
-	p = Popen([cmd, '--interface-description'], stdout = PIPE,
-						    stderr = PIPE)
-        cmdout, cmderr = p.communicate()
-        
-        # TODO: replace ugly hack bellow
-        if not cmdout and sys.platform == 'win32':
-            if os.path.splitext(cmd)[1] == '':
-                cmd += '.py'
-            
-            os.chdir(os.path.join(os.getenv('GISBASE'), 'scripts'))
-	    p = Popen([sys.executable, cmd, '--interface-description'],
-		      stdout = PIPE, stderr = PIPE)
-            cmdout, cmderr = p.communicate()
-        
-        if p.returncode != 0:
-            raise ScriptError, _("Unable to fetch interface description for command '%(cmd)s'."
-                                 "\n\nDetails: %(det)s") % { 'cmd' : cmd, 'det' : decode(cmderr) }
-    
-    except OSError, e:
-        raise ScriptError, _("Unable to fetch interface description for command '%(cmd)s'."
-                             "\n\nDetails: %(det)s") % { 'cmd' : cmd, 'det' : e }
-    
-    # if cmderr and cmderr[:7] != 'WARNING':
-    # raise ScriptError, _("Unable to fetch interface description for command '%(cmd)s'."
-    # "\n\nDetails: %(det)s") % { 'cmd': cmd, 'det' : decode(cmderr) }
-    
-    return cmdout.replace('grass-interface.dtd', os.path.join(os.getenv('GISBASE'), 'etc', 'grass-interface.dtd'))
-
-def parse_interface(name, parser = processTask, blackList = None):
-    """!Parse interface of given GRASS module
-    
-    @param name name of GRASS module to be parsed
-    """
-    enc = locale.getdefaultlocale()[1]
-    if enc and enc.lower() == "cp932":
-        p = re.compile('encoding="' + enc + '"', re.IGNORECASE)
-        tree = etree.fromstring(p.sub('encoding="utf-8"',
-                                      get_interface_description(name).decode(enc).encode("utf-8")))
-    else:
-        tree = etree.fromstring(get_interface_description(name))
-    
-    return parser(tree, blackList = blackList).get_task()
-
-def command_info(cmd):
-    """!Returns meta information for any GRASS command as dictionary
-    with entries for description, keywords, usage, flags, and
-    parameters, e.g.
-    
-    @code
-    >>> gtask.command_info('g.tempfile')
-    
-    {'keywords': ['general', 'map management'],
-     'params': [{'gisprompt': False, 'multiple': False, 'name': 'pid', 'guidependency': '',
-                'default': '', 'age': None, 'required': True, 'value': '',
-                'label': '', 'guisection': '', 'key_desc': [], 'values': [], 'values_desc': [],
-                'prompt': None, 'hidden': False, 'element': None, 'type': 'integer',
-                'description': 'Process id to use when naming the tempfile'}],
-     'flags': [{'description': 'Verbose module output', 'value': False, 'label': '', 'guisection': '',
-                'suppress_required': False, 'hidden': False, 'name': 'verbose'}, {'description': 'Quiet module output',
-                'value': False, 'label': '', 'guisection': '', 'suppress_required': False, 'hidden': False, 'name': 'quiet'}],
-     'description': 'Creates a temporary file and prints the file name.',
-     'usage': 'g.tempfile pid=integer [--verbose] [--quiet]'
-    }
-
-    >>> gtask.command_info('v.buffer')['keywords']
-    
-    ['vector', 'geometry', 'buffer']
-    @endcode
-    """
-    task = parse_interface(cmd)
-    cmdinfo = {}
-    
-    cmdinfo['description'] = task.get_description()
-    cmdinfo['keywords']    = task.get_keywords()
-    cmdinfo['flags']       = flags = task.get_options()['flags']
-    cmdinfo['params']      = params = task.get_options()['params']
-    
-    usage = task.get_name()
-    flags_short = list()
-    flags_long  = list()
-    for f in flags:
-        fname = f.get('name', 'unknown')
-        if len(fname) > 1:
-            flags_long.append(fname)
-        else:
-            flags_short.append(fname)
-    
-    if len(flags_short) > 1:
-        usage += ' [-' + ''.join(flags_short) + ']'
-    
-    for p in params:
-        ptype = ','.join(p.get('key_desc', []))
-        if not ptype:
-            ptype = p.get('type', '')
-        req =  p.get('required', False)
-        if not req:
-           usage += ' ['
-        else:
-            usage += ' '
-        usage += p['name'] + '=' + ptype
-        if p.get('multiple', False):
-            usage += '[,' + ptype + ',...]'
-        if not req:
-            usage += ']'
-        
-    for key in flags_long:
-        usage += ' [--' + key + ']'
-    
-    cmdinfo['usage'] = usage
-    
-    return cmdinfo

Deleted: grass/trunk/lib/python/vector.py
===================================================================
--- grass/trunk/lib/python/vector.py	2013-01-08 08:35:23 UTC (rev 54568)
+++ grass/trunk/lib/python/vector.py	2013-01-08 09:34:42 UTC (rev 54569)
@@ -1,411 +0,0 @@
-"""!@package grass.script.vector
-
- at brief GRASS Python scripting module (vector functions)
-
-Vector related functions to be used in Python scripts.
-
-Usage:
-
- at code
-from grass.script import vector as grass
-
-grass.vector_db(map)
-...
- at endcode
-
-(C) 2008-2010 by the GRASS Development Team
-This program is free software under the GNU General Public
-License (>=v2). Read the file COPYING that comes with GRASS
-for details.
-
- at author Glynn Clements
- at author Martin Landa <landa.martin gmail.com>
-"""
-
-import os
-import types
-import copy
-import __builtin__
-
-from core import *
-
-# run "v.db.connect -g ..." and parse output
-
-def vector_db(map, **args):
-    """!Return the database connection details for a vector map
-    (interface to `v.db.connect -g'). Example:
-    
-    \code
-    >>> grass.vector_db('lakes')
-    {1: {'layer': 1, 'name': '',
-    'database': '/home/martin/grassdata/nc_spm_08/PERMANENT/dbf/',
-    'driver': 'dbf', 'key': 'cat', 'table': 'lakes'}}
-    \endcode
-    
-    @param map vector map
-    @param args other v.db.connect's arguments
-    
-    @return dictionary
-    """
-    s = read_command('v.db.connect', quiet = True, flags = 'g', map = map, sep = ';', **args)
-    result = {}
-    
-    for l in s.splitlines():
-	f = l.split(';')
-	if len(f) != 5:
-	    continue
-        
-        if '/' in f[0]:
-            f1 = f[0].split('/')
-            layer = f1[0]
-            name = f1[1]
-        else:
-            layer = f[0]
-            name = ''
-            
-	result[int(layer)] = {
-            'layer'    : int(layer),
-            'name'     : name,
-            'table'    : f[1],
-            'key'      : f[2],
-            'database' : f[3],
-            'driver'   : f[4] }
-    
-    return result
-
-def vector_layer_db(map, layer):
-    """!Return the database connection details for a vector map layer.
-    If db connection for given layer is not defined, fatal() is called.
-    
-    @param map map name
-    @param layer layer number
-    
-    @return parsed output
-    """
-    try:
-        f = vector_db(map)[int(layer)]
-    except KeyError:
-	fatal(_("Database connection not defined for layer %s") % layer)
-
-    return f
-
-# run "v.info -c ..." and parse output
-
-def vector_columns(map, layer = None, getDict = True, **args):
-    """!Return a dictionary (or a list) of the columns for the
-    database table connected to a vector map (interface to `v.info
-    -c').
-
-    @code
-    >>> vector_columns(urbanarea, getDict = True)
-    {'UA_TYPE': {'index': 4, 'type': 'CHARACTER'}, 'UA': {'index': 2, 'type': 'CHARACTER'}, 'NAME': {'index': 3, 'type': 'CHARACTER'}, 'OBJECTID': {'index': 1, 'type': 'INTEGER'}, 'cat': {'index': 0, 'type': 'INTEGER'}}
-
-    >>> vector_columns(urbanarea, getDict = False)
-    ['cat', 'OBJECTID', 'UA', 'NAME', 'UA_TYPE']
-    @endcode
-    
-    @param map map name
-    @param layer layer number or name (None for all layers)
-    @param getDict True to return dictionary of columns otherwise list of column names is returned
-    @param args (v.info's arguments)
-    
-    @return dictionary/list of columns
-    """
-    s = read_command('v.info', flags = 'c', map = map, layer = layer, quiet = True, **args)
-    if getDict:
-        result = dict()
-    else:
-        result = list()
-    i = 0
-    for line in s.splitlines():
-	ctype, cname = line.split('|')
-        if getDict:
-            result[cname] = { 'type' : ctype,
-                              'index' : i }
-        else:
-            result.append(cname)
-        i+=1
-    
-    return result
-
-# add vector history
-
-def vector_history(map):
-    """!Set the command history for a vector map to the command used to
-    invoke the script (interface to `v.support').
-
-    @param map mapname
-
-    @return v.support output
-    """
-    run_command('v.support', map = map, cmdhist = os.environ['CMDLINE'])
-
-# run "v.info -t" and parse output
-
-def vector_info_topo(map):
-    """!Return information about a vector map (interface to `v.info
-    -t'). Example:
-
-    \code
-    >>> grass.vector_info_topo('lakes')
-    {'kernels': 0, 'lines': 0, 'centroids': 15279,
-    'boundaries': 27764, 'points': 0, 'faces': 0,
-    'primitives': 43043, 'islands': 7470, 'nodes': 35234, 'map3d': False, 'areas': 15279}
-    \endcode
-    
-    @param map map name
-
-    @return parsed output
-    """
-    s = read_command('v.info', flags = 't', map = map)
-    ret = parse_key_val(s, val_type = int)
-    if 'map3d' in ret:
-        ret['map3d'] = bool(ret['map3d'])
-    
-    return ret
-
-
-# run "v.info -get ..." and parse output
-
-def vector_info(map):
-    """!Return information about a vector map (interface to
-    `v.info'). Example:
-
-    \code
-    >>> grass.vector_info('random_points')
-    {'comment': '', 'projection': 'x,y', 'creator': 'soeren', 'holes': 0, 
-     'primitives': 20, 'kernels': 0, 'scale': '1:1', 'title': '', 
-     'west': 0.046125489999999998, 'top': 2376.133159, 'boundaries': 0, 
-     'location': 'XYLocation', 'nodes': 0, 'east': 0.97305646000000001, 
-     'source_date': 'Mon Aug 29 10:55:57 2011', 'north': 0.9589993, 
-     'format': 'native', 'faces': 0, 'centroids': 0, 
-     'digitization_threshold': '0.000000', 'islands': 0, 'level': 2, 
-     'mapset': 'test', 'areas': 0, 'name': 'random_points', 
-     'database': '/home/soeren/grassdata', 'bottom': 22.186596999999999, 
-     'lines': 0, 'points': 20, 'map3d': True, 'volumes': 0, 'num_dblinks': 0, 
-     'organization': '', 'south': 0.066047099999999997}
-    
-    \endcode
-    @param map map name
-    
-    @return parsed vector info
-    """
-
-    s = read_command('v.info', flags = 'get', map = map)
-    
-    kv = parse_key_val(s)
-    for k in ['north', 'south', 'east', 'west', 'top', 'bottom']:
-	kv[k] = float(kv[k])
-    for k in ['level', 'num_dblinks']:
-	kv[k] = int(kv[k])
-    for k in ['nodes', 'points', 'lines', 'boundaries', 'centroids', 'areas', 'islands', 'primitives']:
-	kv[k] = int(kv[k])
-    if 'map3d' in kv:
-        kv['map3d'] = bool(int(kv['map3d']))
-        if kv['map3d']:
-            for k in ['faces', 'kernels', 'volumes', 'holes']:
-                kv[k] = int(kv[k])
-
-    return kv
-
-
-# interface for v.db.select
-
-def vector_db_select(map, layer = 1, **kwargs):
-    """!Get attribute data of selected vector map layer.
-
-    Function returns list of columns and dictionary of values ordered by
-    key column value. Example:
-
-    \code
-    >>> print grass.vector_db_select('lakes')['columns']
-    ['cat', 'AREA', 'PERIMETER', 'FULL_HYDRO', 'FULL_HYDR2', 'FTYPE', 'FCODE', 'NAME']
-    >>> print grass.vector_db_select('lakes')['values'][3]
-    ['3', '19512.86146', '708.44683', '4', '55652', 'LAKE/POND', '39000', '']
-    >>> print grass.vector_db_select('lakes', columns = 'FTYPE')['values'][3]
-    ['LAKE/POND']
-    \endcode
-
-    @param map map name
-    @param layer layer number
-    @param kwargs v.db.select options
-
-    @return dictionary ('columns' and 'values')
-    """
-    try:
-        key = vector_db(map = map)[layer]['key']
-    except KeyError:
-        error(_('Missing layer %(layer)d in vector map <%(map)s>') % \
-                  { 'layer' : layer, 'map' : map })
-        return { 'columns' : [], 'values' : {} }
-        
-    if 'columns' in kwargs:
-        if key not in kwargs['columns'].split(','):
-            # add key column if missing
-            debug("Adding key column to the output")
-            kwargs['columns'] += ',' + key
-    
-    ret = read_command('v.db.select',
-                       map = map,
-                       layer = layer,
-                       **kwargs)
-    
-    if not ret:
-        error(_('vector_db_select() failed'))
-        return { 'columns' : [], 'values' : {} }
-    
-    columns = []
-    values = {}
-    for line in ret.splitlines():
-        if not columns:
-            columns = line.split('|')
-            key_index = columns.index(key)
-            continue
-        
-        value = line.split('|')
-        key_value = int(value[key_index])
-        values[key_value] = line.split('|')
-    
-    return { 'columns' : columns,
-             'values' : values }
-
-# interface to v.what
-def vector_what(map, coord, distance = 0.0, ttype = None):
-    """!Query vector map at given locations
-    
-    To query one vector map at one location
-    @code
-    print grass.vector_what(map = 'archsites', coord = (595743, 4925281), distance = 250)
-
-    [{'Category': 8, 'Map': 'archsites', 'Layer': 1, 'Key_column': 'cat',
-      'Database': '/home/martin/grassdata/spearfish60/PERMANENT/dbf/',
-      'Mapset': 'PERMANENT', 'Driver': 'dbf',
-      'Attributes': {'str1': 'No_Name', 'cat': '8'},
-      'Table': 'archsites', 'Type': 'Point', 'Id': 8}]
-    @endcode
-
-    To query one vector map with multiple layers (no additional parameters required)
-    @code
-    for q in grass.vector_what(map = 'some_map', coord = (596532.357143,4920486.21429), distance = 100.0):
-        print q['Map'], q['Layer'], q['Attributes']
-
-    new_bug_sites 1 {'str1': 'Beetle_site', 'GRASSRGB': '', 'cat': '80'}
-    new_bug_sites 2 {'cat': '80'}
-    @endcode
-
-    To query more vector maps at one location
-    @code
-    for q in grass.vector_what(map = ('archsites', 'roads'), coord = (595743, 4925281),
-                               distance = 250):
-        print q['Map'], q['Attributes']
-                            
-    archsites {'str1': 'No_Name', 'cat': '8'}
-    roads {'label': 'interstate', 'cat': '1'}
-    @endcode
-
-    To query one vector map at more locations
-    @code
-    for q in grass.vector_what(map = 'archsites', coord = [(595743, 4925281), (597950, 4918898)],
-                               distance = 250):
-        print q['Map'], q['Attributes']
-
-    archsites {'str1': 'No_Name', 'cat': '8'}
-    archsites {'str1': 'Bob_Miller', 'cat': '22'}
-    @endcode
-
-    @param map vector map(s) to query given as string or list/tuple
-    @param coord coordinates of query given as tuple (easting, northing) or list of tuples
-    @param distance query threshold distance (in map units)
-    @param ttype list of topology types (default of v.what are point, line, area, face)
-
-    @return parsed list
-    """
-    if "LC_ALL" in os.environ:
-        locale = os.environ["LC_ALL"]
-        os.environ["LC_ALL"] = "C"
-
-    if type(map) in (types.StringType, types.UnicodeType):
-        map_list = [map]
-    else:
-        map_list = map
-    
-    layer_list = ['-1'] * len(map_list)
-    
-    coord_list = list()
-    if type(coord) is types.TupleType:
-        coord_list.append('%f,%f' % (coord[0], coord[1]))
-    else:
-        for e, n in coord:
-            coord_list.append('%f,%f' % (e, n))
-    
-    cmdParams = dict(quiet      = True,
-                     flags      = 'ag',
-                     map        = ','.join(map_list),
-                     layer      = ','.join(layer_list),
-                     coordinates = ','.join(coord_list),
-                     distance   = float(distance))
-    if ttype:
-        cmdParams['type'] = ','.join(ttype)
-
-    ret = read_command('v.what',
-                       **cmdParams)
-    
-    if "LC_ALL" in os.environ:
-        os.environ["LC_ALL"] = locale
-        
-    data = list()
-    if not ret:
-        return data
-    
-    dict_attrb = None
-    dict_map = None
-    dict_layer = None
-    attr_pseudo_key = 'Attributes'
-    for item in ret.splitlines():
-        try:
-            key, value = __builtin__.map(lambda x: x.strip(), item.split('=', 1))
-        except ValueError:
-            continue
-        if key in ('East', 'North'):
-            continue
-        
-        if key == 'Map':
-            # attach the last one from the previous map
-            if dict_layer is not None:
-                dict_main = copy.copy(dict_map)
-                dict_main.update(dict_layer)
-                data.append(dict_main)
-            dict_map  = { key : value }
-            dict_layer = None
-            dict_attrb = None
-        elif key == 'Layer':
-            # attach the last the previous Layer
-            if dict_layer is not None:
-                dict_main = copy.copy(dict_map)
-                dict_main.update(dict_layer)
-                data.append(dict_main)
-            dict_layer = { key: int(value) }
-            dict_attrb = None
-        elif key == 'Key_column':
-            dict_layer[key] = value
-            dict_attrb = dict()
-            dict_layer[attr_pseudo_key] = dict_attrb
-        elif dict_attrb is not None:
-            dict_attrb[key] = value
-        elif dict_layer is not None:
-            if key == 'Category':
-                dict_layer[key] = int(value)
-            else:
-                dict_layer[key] = value
-        else:
-            dict_map[key] = value
-            # TODO: there are some keys which has non-string values
-            # examples: Sq_Meters, Hectares, Acres, Sq_Miles
-    
-    # attach the last one
-    if dict_layer is not None:
-        dict_main = copy.copy(dict_map)
-        dict_main.update(dict_layer)
-        data.append(dict_main)
-    
-    return data



More information about the grass-commit mailing list