[GRASS-SVN] r53780 - in grass/trunk: gui/wxpython/core lib/python
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Nov 12 10:13:54 PST 2012
Author: zarch
Date: 2012-11-12 10:13:53 -0800 (Mon, 12 Nov 2012)
New Revision: 53780
Modified:
grass/trunk/gui/wxpython/core/globalvar.py
grass/trunk/lib/python/core.py
Log:
Move gui.wxpython.core.globalvar.GetGRASSCommands to lib.python.core.get_commands
Modified: grass/trunk/gui/wxpython/core/globalvar.py
===================================================================
--- grass/trunk/gui/wxpython/core/globalvar.py 2012-11-12 16:58:11 UTC (rev 53779)
+++ grass/trunk/gui/wxpython/core/globalvar.py 2012-11-12 18:13:53 UTC (rev 53780)
@@ -28,21 +28,22 @@
from core.debug import Debug
sys.path.append(os.path.join(ETCDIR, "python"))
-import grass.script as grass
+from grass.script.core import get_commands
+
def CheckWxVersion(version = [2, 8, 11, 0]):
"""!Check wx version"""
ver = wx.version().split(' ')[0]
if map(int, ver.split('.')) < version:
return False
-
+
return True
def CheckForWx():
"""!Try to import wx module and check its version"""
if 'wx' in sys.modules.keys():
return
-
+
minVersion = [2, 8, 1, 1]
try:
try:
@@ -53,7 +54,7 @@
wxversion.ensureMinimal(str(minVersion[0]) + '.' + str(minVersion[1]))
import wx
version = wx.version().split(' ')[0]
-
+
if map(int, version.split('.')) < minVersion:
raise ValueError('Your wxPython version is %s.%s.%s.%s' % tuple(version.split('.')))
@@ -67,7 +68,7 @@
except locale.Error, e:
print >> sys.stderr, "Unable to set locale:", e
os.environ['LC_ALL'] = ''
-
+
if not os.getenv("GRASS_WXBUNDLED"):
CheckForWx()
import wx
@@ -84,7 +85,7 @@
FNPageStyle = FN.FNB_VC8 | \
FN.FNB_BACKGROUND_GRADIENT | \
FN.FNB_NODRAG | \
- FN.FNB_TABS_BORDER_SIMPLE
+ FN.FNB_TABS_BORDER_SIMPLE
FNPageDStyle = FN.FNB_FANCY_TABS | \
FN.FNB_BOTTOM | \
@@ -110,50 +111,7 @@
else:
BIN_EXT = SCT_EXT = ''
-def GetGRASSCommands():
- """!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)
- """
- gisbase = os.environ['GISBASE']
- cmd = list()
- if sys.platform == 'win32':
- scripts = { SCT_EXT : list() }
- else:
- scripts = {}
-
- # scan bin/
- if os.path.exists(os.path.join(gisbase, 'bin')):
- 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)
-
- # scan scripts/
- if os.path.exists(os.path.join(gisbase, 'scripts')):
- for fname in os.listdir(os.path.join(gisbase, 'scripts')):
- if scripts: # win32
- name, ext = os.path.splitext(fname)
- if ext in scripts.keys():
- scripts[ext].append(name)
- cmd.append(name)
- else:
- cmd.append(fname)
-
- # scan gui/scripts/
- if os.path.exists(os.path.join(gisbase, 'etc', 'gui', 'scripts')):
- os.environ["PATH"] = os.getenv("PATH") + os.pathsep + os.path.join(gisbase, 'etc', 'gui', 'scripts')
- cmd = cmd + os.listdir(os.path.join(gisbase, 'etc', 'gui', 'scripts'))
-
- return set(cmd), scripts
-
def UpdateGRASSAddOnCommands(eList = None):
"""!Update list of available GRASS AddOns commands to use when
parsing string from the command line
@@ -161,14 +119,14 @@
@param eList list of AddOns commands to remove
"""
global grassCmd, grassScripts
-
+
# scan addons (path)
addonPath = os.getenv('GRASS_ADDON_PATH', '')
addonBase = os.getenv('GRASS_ADDON_BASE')
if addonBase:
addonPath += os.pathsep + os.path.join(addonBase, 'bin') + os.pathsep + \
os.path.join(addonBase, 'scripts')
-
+
# remove commands first
if eList:
for ext in eList:
@@ -201,11 +159,11 @@
grassCmd.add(fname)
Debug.msg(3, "AddOn commands: %s", fname)
nCmd += 1
-
+
Debug.msg(1, "Number of new AddOn commands: %d", nCmd)
"""@brief Collected GRASS-relared binaries/scripts"""
-grassCmd, grassScripts = GetGRASSCommands()
+grassCmd, grassScripts = get_commands()
Debug.msg(1, "Number of GRASS commands: %d", len(grassCmd))
UpdateGRASSAddOnCommands()
Modified: grass/trunk/lib/python/core.py
===================================================================
--- grass/trunk/lib/python/core.py 2012-11-12 16:58:11 UTC (rev 53779)
+++ grass/trunk/lib/python/core.py 2012-11-12 18:13:53 UTC (rev 53780)
@@ -54,17 +54,17 @@
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 @@
enc = locale.getdefaultlocale()[1]
if enc:
return string.decode(enc)
-
+
return string
def _make_val(val):
@@ -93,6 +93,50 @@
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 @@
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 @@
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 @@
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 @@
@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 @@
@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 @@
@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 @@
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 @@
@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 percent(i, n, s):
"""!Display a progress info message using `g.message -p`
-
+
@code
message(_("Percent complete..."))
n = 100
@@ -349,7 +393,7 @@
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 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 @@
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 @@
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 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 @@
if not s:
return result
-
+
if vsep:
lines = s.split(vsep)
try:
@@ -533,7 +577,7 @@
pass
else:
lines = s.splitlines()
-
+
for line in lines:
kv = line.split(sep, 1)
k = kv[0].strip()
@@ -541,26 +585,26 @@
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 @@
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 @@
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 @@
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 @@
"""
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 @@
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 @@
dictionary. Example:
\param region3d True to get 3D region
-
+
\code
>>> region = grass.region()
>>> [region[key] for key in "nsew"]
@@ -718,7 +762,7 @@
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 @@
if k not in reg:
continue
reg[k] = int(reg[k])
-
+
return reg
def region_env(region3d = False,
@@ -765,22 +809,22 @@
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 @@
('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 @@
>>> 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 @@
>>> 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 @@
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 @@
continue
if mapset:
result[mapset].extend(line.split())
-
+
return result
def _concat(xs):
@@ -910,9 +954,9 @@
>>> 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 @@
@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 @@
>>> 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 @@
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 @@
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 @@
# 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 @@
except:
found = False
nuldev.close()
-
+
return found
# try to remove a file, without complaints
@@ -1170,7 +1214,7 @@
"""!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 @@
quiet = True)
if not mapsets:
fatal(_("Unable to list mapsets"))
-
+
return mapsets.splitlines()
# interface to `g.proj -c`
@@ -1194,7 +1238,7 @@
"""!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 @@
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 @@
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 @@
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 @@
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 @@
'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 @@
flags = 'rge')
for k, v in data.iteritems():
data[k.strip()] = v.replace('"', '').strip()
-
+
return data
# get debug_level
More information about the grass-commit
mailing list