|
@@ -54,17 +54,17 @@ class Popen(subprocess.Popen):
|
|
|
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):
|
|
@@ -80,7 +80,7 @@ def decode(string):
|
|
|
enc = locale.getdefaultlocale()[1]
|
|
|
if enc:
|
|
|
return string.decode(enc)
|
|
|
-
|
|
|
+
|
|
|
return string
|
|
|
|
|
|
def _make_val(val):
|
|
@@ -93,6 +93,50 @@ def _make_val(val):
|
|
|
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, 'bin')):
|
|
|
+ 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:
|
|
@@ -146,14 +190,14 @@ def start_command(prog, flags = "", overwrite = False, quiet = False, verbose =
|
|
|
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 = {}
|
|
@@ -165,11 +209,11 @@ def start_command(prog, flags = "", overwrite = False, quiet = False, verbose =
|
|
|
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):
|
|
@@ -201,7 +245,7 @@ def pipe_command(*args, **kwargs):
|
|
|
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)
|
|
|
|
|
@@ -216,7 +260,7 @@ def feed_command(*args, **kwargs):
|
|
|
|
|
|
@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
|
|
@@ -228,7 +272,7 @@ def read_command(*args, **kwargs):
|
|
|
|
|
|
@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)
|
|
@@ -253,7 +297,7 @@ def parse_command(*args, **kwargs):
|
|
|
|
|
|
@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
|
|
@@ -263,14 +307,14 @@ def parse_command(*args, **kwargs):
|
|
|
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)
|
|
@@ -324,10 +368,10 @@ def debug(msg, debug = 1):
|
|
|
@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')
|
|
@@ -341,7 +385,7 @@ def info(msg):
|
|
|
|
|
|
def percent(i, n, s):
|
|
|
"""!Display a progress info message using `g.message -p`
|
|
|
-
|
|
|
+
|
|
|
@code
|
|
|
message(_("Percent complete..."))
|
|
|
n = 100
|
|
@@ -349,7 +393,7 @@ def percent(i, n, s):
|
|
|
percent(i, n, 1)
|
|
|
percent(1, 1, 1)
|
|
|
@endcode
|
|
|
-
|
|
|
+
|
|
|
@param i current item
|
|
|
@param n total number of items
|
|
|
@param s increment size
|
|
@@ -365,31 +409,31 @@ def warning(msg):
|
|
|
|
|
|
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
|
|
@@ -439,11 +483,11 @@ def parser():
|
|
|
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):
|
|
@@ -451,15 +495,15 @@ def parser():
|
|
|
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
|
|
@@ -467,22 +511,22 @@ def parser():
|
|
|
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):
|
|
@@ -524,7 +568,7 @@ def parse_key_val(s, sep = '=', dflt = None, val_type = None, vsep = None):
|
|
|
|
|
|
if not s:
|
|
|
return result
|
|
|
-
|
|
|
+
|
|
|
if vsep:
|
|
|
lines = s.split(vsep)
|
|
|
try:
|
|
@@ -533,7 +577,7 @@ def parse_key_val(s, sep = '=', dflt = None, val_type = None, vsep = None):
|
|
|
pass
|
|
|
else:
|
|
|
lines = s.splitlines()
|
|
|
-
|
|
|
+
|
|
|
for line in lines:
|
|
|
kv = line.split(sep, 1)
|
|
|
k = kv[0].strip()
|
|
@@ -541,26 +585,26 @@ def parse_key_val(s, sep = '=', dflt = None, val_type = None, vsep = None):
|
|
|
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
|
|
|
+ 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
|
|
|
-
|
|
|
+ @return The dictionary
|
|
|
+
|
|
|
A text file with this content:
|
|
|
\code
|
|
|
a: Hello
|
|
@@ -568,16 +612,16 @@ def _text_to_key_value_dict(filename, sep=":", val_sep=","):
|
|
|
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)
|
|
@@ -588,11 +632,11 @@ def _text_to_key_value_dict(filename, sep=":", val_sep=","):
|
|
|
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:
|
|
@@ -604,33 +648,33 @@ def _text_to_key_value_dict(filename, sep=":", val_sep=","):
|
|
|
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=":",
|
|
|
+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 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
|
|
@@ -641,9 +685,9 @@ def compare_key_value_text_files(filename_a, filename_b, sep=":",
|
|
|
"""
|
|
|
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):
|
|
@@ -664,7 +708,7 @@ def compare_key_value_text_files(filename_a, filename_b, sep=":",
|
|
|
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():
|
|
@@ -702,7 +746,7 @@ def region(region3d = False, complete = False):
|
|
|
dictionary. Example:
|
|
|
|
|
|
\param region3d True to get 3D region
|
|
|
-
|
|
|
+
|
|
|
\code
|
|
|
>>> region = grass.region()
|
|
|
>>> [region[key] for key in "nsew"]
|
|
@@ -718,7 +762,7 @@ def region(region3d = False, complete = False):
|
|
|
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',
|
|
@@ -726,7 +770,7 @@ def region(region3d = False, complete = False):
|
|
|
if k not in reg:
|
|
|
continue
|
|
|
reg[k] = int(reg[k])
|
|
|
-
|
|
|
+
|
|
|
return reg
|
|
|
|
|
|
def region_env(region3d = False,
|
|
@@ -765,22 +809,22 @@ def region_env(region3d = False,
|
|
|
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'),
|
|
@@ -798,12 +842,12 @@ def region_env(region3d = False,
|
|
|
('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
|
|
@@ -835,7 +879,7 @@ def find_file(name, element = 'cell', mapset = None):
|
|
|
>>> 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)
|
|
@@ -861,7 +905,7 @@ def list_grouped(type, check_search_path = True):
|
|
|
>>> 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
|
|
|
|
|
@@ -876,7 +920,7 @@ def list_grouped(type, check_search_path = True):
|
|
|
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 == "":
|
|
@@ -891,7 +935,7 @@ def list_grouped(type, check_search_path = True):
|
|
|
continue
|
|
|
if mapset:
|
|
|
result[mapset].extend(line.split())
|
|
|
-
|
|
|
+
|
|
|
return result
|
|
|
|
|
|
def _concat(xs):
|
|
@@ -910,9 +954,9 @@ def list_pairs(type):
|
|
|
>>> 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]
|
|
@@ -930,7 +974,7 @@ def list_strings(type):
|
|
|
@endcode
|
|
|
|
|
|
@param type element type
|
|
|
-
|
|
|
+
|
|
|
@return list of strings ('map@@mapset')
|
|
|
"""
|
|
|
return ["%s@%s" % pair for pair in list_pairs(type)]
|
|
@@ -990,7 +1034,7 @@ def mlist_grouped(type, pattern = None, check_search_path = True, flag = ''):
|
|
|
>>> 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
|
|
@@ -1005,7 +1049,7 @@ def mlist_grouped(type, pattern = None, check_search_path = True, flag = ''):
|
|
|
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():
|
|
@@ -1014,12 +1058,12 @@ def mlist_grouped(type, pattern = None, check_search_path = True, flag = ''):
|
|
|
except ValueError:
|
|
|
warning(_("Invalid element '%s'") % line)
|
|
|
continue
|
|
|
-
|
|
|
+
|
|
|
if mapset in result:
|
|
|
- result[mapset].append(name)
|
|
|
- else:
|
|
|
- result[mapset] = [name, ]
|
|
|
-
|
|
|
+ result[mapset].append(name)
|
|
|
+ else:
|
|
|
+ result[mapset] = [name, ]
|
|
|
+
|
|
|
return result
|
|
|
|
|
|
# color parsing
|
|
@@ -1108,7 +1152,7 @@ def basename(path, ext = None):
|
|
|
# find a program (replacement for "which")
|
|
|
|
|
|
def find_program(pgm, args = []):
|
|
|
- """!Attempt to run a program, with optional arguments.
|
|
|
+ """!Attempt to run a program, with optional arguments.
|
|
|
|
|
|
@param pgm program name
|
|
|
@param args list of arguments
|
|
@@ -1126,7 +1170,7 @@ def find_program(pgm, args = []):
|
|
|
except:
|
|
|
found = False
|
|
|
nuldev.close()
|
|
|
-
|
|
|
+
|
|
|
return found
|
|
|
|
|
|
# try to remove a file, without complaints
|
|
@@ -1170,7 +1214,7 @@ 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:
|
|
@@ -1183,7 +1227,7 @@ def mapsets(search_path = False):
|
|
|
quiet = True)
|
|
|
if not mapsets:
|
|
|
fatal(_("Unable to list mapsets"))
|
|
|
-
|
|
|
+
|
|
|
return mapsets.splitlines()
|
|
|
|
|
|
# interface to `g.proj -c`
|
|
@@ -1194,7 +1238,7 @@ def create_location(dbase, location,
|
|
|
"""!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
|
|
@@ -1212,13 +1256,13 @@ def create_location(dbase, location,
|
|
|
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,
|
|
@@ -1247,12 +1291,12 @@ def create_location(dbase, 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))
|
|
|
|
|
@@ -1267,12 +1311,12 @@ def create_location(dbase, location,
|
|
|
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
|
|
|
"""
|
|
@@ -1281,7 +1325,7 @@ def _create_location_xy(database, location):
|
|
|
os.chdir(database)
|
|
|
os.mkdir(location)
|
|
|
os.mkdir(os.path.join(location, 'PERMANENT'))
|
|
|
-
|
|
|
+
|
|
|
# create DEFAULT_WIND and WIND files
|
|
|
regioninfo = ['proj: 0',
|
|
|
'zone: 0',
|
|
@@ -1301,16 +1345,16 @@ def _create_location_xy(database, location):
|
|
|
'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))
|
|
@@ -1332,7 +1376,7 @@ def version():
|
|
|
flags = 'rge')
|
|
|
for k, v in data.iteritems():
|
|
|
data[k.strip()] = v.replace('"', '').strip()
|
|
|
-
|
|
|
+
|
|
|
return data
|
|
|
|
|
|
# get debug_level
|