From 90639aecee2e557b42b2f72d6731e0ea38a8bf1e Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 20:40:41 +0200 Subject: [PATCH 01/22] lib/init/grass: Simplify removing the tmpdir. shutil.rmtree removes directories recursively, so no need for the wrapper function/classes. --- lib/init/grass.py | 41 ++++------------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index bfca4dc4..f4f53ad8 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -41,6 +41,7 @@ import sys import os import atexit +import shutil import string import subprocess import re @@ -172,13 +173,6 @@ def try_remove(path): pass -def try_rmdir(path): - try: - os.rmdir(path) - except: - pass - - def clean_env(gisrc): env_curr = read_gisrc(gisrc) env_new = {} @@ -190,32 +184,6 @@ def clean_env(gisrc): write_gisrc(env_new, gisrc) -def cleanup_dir(path): - if not path: - return - - for root, dirs, files in os.walk(path, topdown=False): - for name in files: - try_remove(os.path.join(root, name)) - for name in dirs: - try_rmdir(os.path.join(root, name)) - - -class Cleaner(object): # pylint: disable=R0903 - """Holds directories and files which needs to be cleaned or deleted""" - def __init__(self): - self.tmpdir = None - - def cleanup(self): - """This can be registered with atexit - - Object can then still change and add or remove directories to clean""" - # all exits after setting up tmp dirs (system/location) should - # also tidy it up - cleanup_dir(self.tmpdir) - try_rmdir(self.tmpdir) - - def fatal(msg): sys.stderr.write("%s: " % _('ERROR') + msg + os.linesep) sys.exit(_("Exiting...")) @@ -2106,10 +2074,9 @@ def main(): # Create the temporary directory and session grassrc file tmpdir = create_tmp(user, gis_lock) - cleaner = Cleaner() - cleaner.tmpdir = tmpdir - # object is not destroyed when its method is registered - atexit.register(cleaner.cleanup) + # Remove the tmpdir + # The removal will be executed when the python process terminates. + atexit.register(lambda: shutil.rmtree(tmpdir, ignore_errors=True)) # Create the session grassrc file gisrc = create_gisrc(tmpdir, gisrcrc) From 785492b3a2c9e4708ba2504549473b032eebeae1 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 20:43:30 +0200 Subject: [PATCH 02/22] lib/init/grass: Fix erroneous comment. The function is being used later in this file. --- lib/init/grass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index f4f53ad8..23865c43 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -108,7 +108,7 @@ def encode(string, encoding=None): raise TypeError("can only accept types str and bytes") -# currently not used, see https://trac.osgeo.org/grass/ticket/3508 +# see https://trac.osgeo.org/grass/ticket/3508 def to_text_string(obj, encoding=ENCODING): """Convert `obj` to (unicode) text string""" if PY2: From 39d047b2b716937f7b629cbd328557db2b541708 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 20:51:51 +0200 Subject: [PATCH 03/22] lib/init/grass: Simplify encode()/decode() functions. --- lib/init/grass.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 23865c43..ea71e0a1 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -58,31 +58,28 @@ print("Default locale not found, using UTF-8") # intentionally not translatable -def decode(bytes_, encoding=None): +def decode(bytes_, encoding=ENCODING): """Decode bytes with default locale and return (unicode) string Adapted from lib/python/core/utils.py No-op if parameter is not bytes (assumed unicode string). :param bytes bytes_: the bytes to decode - :param encoding: encoding to be used, default value is None + :param encoding: encoding to be used, default value is the system's default + encoding or, if that cannot be determined, 'UTF-8'. """ if sys.version_info.major >= 3: unicode = str if isinstance(bytes_, unicode): return bytes_ elif isinstance(bytes_, bytes): - if encoding is None: - enc = ENCODING - else: - enc = encoding - return bytes_.decode(enc) + return bytes_.decode(encoding) else: # if something else than text raise TypeError("can only accept types str and bytes") -def encode(string, encoding=None): +def encode(string, encoding=ENCODING): """Encode string with default locale and return bytes with that encoding Adapted from lib/python/core/utils.py @@ -90,7 +87,8 @@ def encode(string, encoding=None): This ensures garbage in, garbage out. :param str string: the string to encode - :param encoding: encoding to be used, default value is None + :param encoding: encoding to be used, default value is the system's default + encoding or, if that cannot be determined, 'UTF-8'. """ if sys.version_info.major >= 3: unicode = str @@ -98,11 +96,7 @@ def encode(string, encoding=None): return string # this also tests str in Py3: elif isinstance(string, unicode): - if encoding is None: - enc = ENCODING - else: - enc = encoding - return string.encode(enc) + return string.encode(encoding) else: # if something else than text raise TypeError("can only accept types str and bytes") From e60e034551387f44bcabf5a33bda866e10997505 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 21:11:56 +0200 Subject: [PATCH 04/22] lib/init/grass: Move all the imports at the beginning of the file. --- lib/init/grass.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index ea71e0a1..d552a6f9 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -41,9 +41,12 @@ import sys import os import atexit +import gettext import shutil +import signal import string import subprocess +import types import re import platform import tempfile @@ -114,7 +117,6 @@ def to_text_string(obj, encoding=ENCODING): if PY2: - import types string_types = basestring, integer_types = (int, long) class_types = (type, types.ClassType) @@ -151,7 +153,6 @@ def to_text_string(obj, encoding=ENCODING): gisbase = os.path.normpath(gisbase) # i18N -import gettext # TODO: is this needed or even desirable when we have set_language()? gettext.install('grasslibs', os.path.join(gisbase, 'locale')) @@ -1584,7 +1585,6 @@ def close_gui(): env = gcore.gisenv() if 'GUI_PID' not in env: return - import signal for pid in env['GUI_PID'].split(','): debug("Exiting GUI with pid={0}".format(pid)) try: From 47ff016263714d6a4e9f5444233a709783d2e340 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 21:16:11 +0200 Subject: [PATCH 05/22] lib/init/grass: Simplify clean_env(). "clean_env()" is only being called once. Even if it gets called multiple times in the future, it is unlikely that it will be used with a different "gisrc". --- lib/init/grass.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index d552a6f9..e796f7fd 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -168,14 +168,14 @@ def try_remove(path): pass -def clean_env(gisrc): +def clean_env(): + gisrc = os.environ['GISRC'] env_curr = read_gisrc(gisrc) env_new = {} for k, v in env_curr.items(): if k.endswith('PID') or k.startswith('MONITOR'): continue env_new[k] = v - write_gisrc(env_new, gisrc) @@ -1815,7 +1815,7 @@ def clean_all(): clean_temp() # save 'last used' GISRC after removing variables which shouldn't # be saved, e.g. d.mon related - clean_env(os.environ['GISRC']) + clean_env() def grep(pattern, lines): From 193277df9bf8be8354a1493cd980ca4049a8839a Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 21:18:18 +0200 Subject: [PATCH 06/22] lib/init/grass: Just shuffling stuff around Just keeping globals and the initialization stuff at the beginning of the module --- lib/init/grass.py | 135 ++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 70 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index e796f7fd..69a2974e 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -53,6 +53,13 @@ import locale +# mechanism meant for debugging this script (only) +# private global to store if we are debugging +_DEBUG = None + +# for wxpath +_WXPYTHON_BASE = None + # ----+- Python 3 compatibility start -+---- PY2 = sys.version[0] == '2' ENCODING = locale.getdefaultlocale()[1] @@ -61,6 +68,64 @@ print("Default locale not found, using UTF-8") # intentionally not translatable +if PY2: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str +else: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + MAXSIZE = sys.maxsize + +# ----+- Python 3 compatibility end -+---- + +# Variables substituted during build process +if 'GISBASE' in os.environ: + # TODO: should this be something like GRASS_PATH? + # GISBASE marks complete runtime, so no need to get it here when + # setting it up, possible scenario: existing runtime and starting + # GRASS in that, we want to overwrite the settings, not to take it + # possibly same for GRASS_PROJSHARE and others but maybe not + gisbase = os.environ['GISBASE'] +else: + gisbase = "@GISBASE@" +cmd_name = "@START_UP@" +grass_version = "@GRASS_VERSION_NUMBER@" +ld_library_path_var = '@LD_LIBRARY_PATH_VAR@' +if 'GRASS_PROJSHARE' in os.environ: + config_projshare = os.environ['GRASS_PROJSHARE'] +else: + config_projshare = "@CONFIG_PROJSHARE@" + +gisbase = os.path.normpath(gisbase) + +# Get the system name +windows = sys.platform == 'win32' +cygwin = "cygwin" in sys.platform +macosx = "darwin" in sys.platform + +# TODO: it is OK to remove this? +# at the beginning of this file were are happily getting GISBASE +# from the environment and we don't care about inconsistencies it might cause +# The following was commented out because of breaking winGRASS +# if 'GISBASE' in os.environ: +# sys.exit(_("ERROR: GRASS GIS is already running " +# "(environmental variable GISBASE found)")) +# this is not really an issue, we should be able to overpower another session + +# Set GISBASE +os.environ['GISBASE'] = gisbase + +# i18N +# TODO: is this needed or even desirable when we have set_language()? +gettext.install('grasslibs', os.path.join(gisbase, 'locale')) + + def decode(bytes_, encoding=ENCODING): """Decode bytes with default locale and return (unicode) string Adapted from lib/python/core/utils.py @@ -116,47 +181,6 @@ def to_text_string(obj, encoding=ENCODING): return decode(obj, encoding=encoding) -if PY2: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str -else: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - MAXSIZE = sys.maxsize - -# ----+- Python 3 compatibility end -+---- - -# Variables substituted during build process -if 'GISBASE' in os.environ: - # TODO: should this be something like GRASS_PATH? - # GISBASE marks complete runtime, so no need to get it here when - # setting it up, possible scenario: existing runtime and starting - # GRASS in that, we want to overwrite the settings, not to take it - # possibly same for GRASS_PROJSHARE and others but maybe not - gisbase = os.environ['GISBASE'] -else: - gisbase = "@GISBASE@" -cmd_name = "@START_UP@" -grass_version = "@GRASS_VERSION_NUMBER@" -ld_library_path_var = '@LD_LIBRARY_PATH_VAR@' -if 'GRASS_PROJSHARE' in os.environ: - config_projshare = os.environ['GRASS_PROJSHARE'] -else: - config_projshare = "@CONFIG_PROJSHARE@" - -gisbase = os.path.normpath(gisbase) - -# i18N -# TODO: is this needed or even desirable when we have set_language()? -gettext.install('grasslibs', os.path.join(gisbase, 'locale')) - - def warning(text): sys.stderr.write(_("WARNING") + ': ' + text + os.linesep) @@ -189,11 +213,6 @@ def message(msg): sys.stderr.flush() -# mechanism meant for debugging this script (only) -# private global to store if we are debugging -_DEBUG = None - - def is_debug(): """Returns True if we are in debug mode @@ -258,10 +277,6 @@ def gpath(*args): return os.path.join(gisbase, *args) -# for wxpath -_WXPYTHON_BASE = None - - def wxpath(*args): """Costruct path to file or directory in GRASS wxGUI @@ -1971,26 +1986,6 @@ def parse_cmdline(argv, default_gui): return params -# The main script starts here - -# Get the system name -windows = sys.platform == 'win32' -cygwin = "cygwin" in sys.platform -macosx = "darwin" in sys.platform - -# TODO: it is OK to remove this? -# at the beginning of this file were are happily getting GISBASE -# from the environment and we don't care about inconsistencies it might cause -# The following was commented out because of breaking winGRASS -# if 'GISBASE' in os.environ: -# sys.exit(_("ERROR: GRASS GIS is already running " -# "(environmental variable GISBASE found)")) -# this is not really an issue, we should be able to overpower another session - -# Set GISBASE -os.environ['GISBASE'] = gisbase - - def main(): """The main function which does the whole setup and run procedure From 821f43f1aa3c4cf46f851e554a318883b902d92c Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 21:42:02 +0200 Subject: [PATCH 07/22] lib/init/grass: Group the logging functions together. --- lib/init/grass.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 69a2974e..e5256f05 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -181,10 +181,6 @@ def to_text_string(obj, encoding=ENCODING): return decode(obj, encoding=encoding) -def warning(text): - sys.stderr.write(_("WARNING") + ': ' + text + os.linesep) - - def try_remove(path): try: os.remove(path) @@ -203,16 +199,6 @@ def clean_env(): write_gisrc(env_new, gisrc) -def fatal(msg): - sys.stderr.write("%s: " % _('ERROR') + msg + os.linesep) - sys.exit(_("Exiting...")) - - -def message(msg): - sys.stderr.write(msg + "\n") - sys.stderr.flush() - - def is_debug(): """Returns True if we are in debug mode @@ -240,6 +226,20 @@ def debug(msg): sys.stderr.flush() +def message(msg): + sys.stderr.write(msg + "\n") + sys.stderr.flush() + + +def warning(text): + sys.stderr.write(_("WARNING") + ': ' + text + os.linesep) + + +def fatal(msg): + sys.stderr.write("%s: " % _('ERROR') + msg + os.linesep) + sys.exit(_("Exiting...")) + + def readfile(path): debug("Reading %s" % path) f = open(path, 'r') From 3a5de69baccdad2f4600e9965a2f1f63e4f49349 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 23:42:29 +0200 Subject: [PATCH 08/22] lib/init/grass: Capitalize constants. --- lib/init/grass.py | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index e5256f05..63408a69 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -105,9 +105,9 @@ gisbase = os.path.normpath(gisbase) # Get the system name -windows = sys.platform == 'win32' -cygwin = "cygwin" in sys.platform -macosx = "darwin" in sys.platform +WINDOWS = sys.platform == 'win32' +CYGWIN = "cygwin" in sys.platform +MACOSX = "darwin" in sys.platform # TODO: it is OK to remove this? # at the beginning of this file were are happily getting GISBASE @@ -257,14 +257,14 @@ def writefile(path, s): def call(cmd, **kwargs): """Wrapper for subprocess.call to deal with platform-specific issues""" - if windows: + if WINDOWS: kwargs['shell'] = True return subprocess.call(cmd, **kwargs) def Popen(cmd, **kwargs): # pylint: disable=C0103 """Wrapper for subprocess.Popen to deal with platform-specific issues""" - if windows: + if WINDOWS: kwargs['shell'] = True return subprocess.Popen(cmd, **kwargs) @@ -294,7 +294,7 @@ def wxpath(*args): # using format for most but leaving usage of template for the dynamic ones # two different methods are easy way to implement two phase construction -help_text = r"""GRASS GIS $VERSION_NUMBER +HELP_TEXT = r"""GRASS GIS $VERSION_NUMBER Geographic Resources Analysis Support System (GRASS GIS). {usage}: @@ -383,7 +383,7 @@ def wxpath(*args): def help_message(default_gui): - t = string.Template(help_text) + t = string.Template(HELP_TEXT) s = t.substitute(CMD_NAME=cmd_name, DEFAULT_GUI=default_gui, VERSION_NUMBER=grass_version) sys.stderr.write(s) @@ -607,12 +607,12 @@ def set_paths(grass_config_dir): if not addon_base: addon_base = os.path.join(grass_config_dir, 'addons') os.environ['GRASS_ADDON_BASE'] = addon_base - if not windows: + if not WINDOWS: path_prepend(os.path.join(addon_base, 'scripts'), 'PATH') path_prepend(os.path.join(addon_base, 'bin'), 'PATH') # standard installation - if not windows: + if not WINDOWS: path_prepend(gpath('scripts'), 'PATH') path_prepend(gpath('bin'), 'PATH') @@ -672,7 +672,7 @@ def set_defaults(): pager = "more" elif find_exe("less"): pager = "less" - elif windows: + elif WINDOWS: pager = "more" else: pager = "cat" @@ -680,7 +680,7 @@ def set_defaults(): # GRASS_PYTHON if not os.getenv('GRASS_PYTHON'): - if windows: + if WINDOWS: os.environ['GRASS_PYTHON'] = "python.exe" else: os.environ['GRASS_PYTHON'] = "python" @@ -706,15 +706,15 @@ def set_browser(): # GRASS_HTML_BROWSER browser = os.getenv('GRASS_HTML_BROWSER') if not browser: - if macosx: + if MACOSX: # OSX doesn't execute browsers from the shell PATH - route through a # script browser = gpath('etc', "html_browser_mac.sh") os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b com.apple.helpviewer" - if windows: + if WINDOWS: browser = "start" - elif cygwin: + elif CYGWIN: browser = "explorer" else: # the usual suspects @@ -726,7 +726,7 @@ def set_browser(): browser = b break - elif macosx: + elif MACOSX: # OSX doesn't execute browsers from the shell PATH - route through a # script os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b %s" % browser @@ -741,7 +741,7 @@ def set_browser(): def ensure_home(): """Set HOME if not set on MS Windows""" - if windows and not os.getenv('HOME'): + if WINDOWS and not os.getenv('HOME'): os.environ['HOME'] = os.path.join(os.getenv('HOMEDRIVE'), os.getenv('HOMEPATH')) @@ -758,7 +758,7 @@ def create_initial_gisrc(filename): def check_gui(expected_gui): grass_gui = expected_gui # Check if we are running X windows by checking the DISPLAY variable - if os.getenv('DISPLAY') or windows or macosx: + if os.getenv('DISPLAY') or WINDOWS or MACOSX: # Check if python is working properly if expected_gui in ('wxpython', 'gtext'): nul = open(os.devnull, 'w') @@ -1459,7 +1459,7 @@ def ensure_db_connected(mapset): def get_shell(): # set SHELL on ms windowns # this was at the very beginning of the script but it can be anywhere - if windows: + if WINDOWS: if os.getenv('GRASS_SH'): os.environ['SHELL'] = os.getenv('GRASS_SH') if not os.getenv('SHELL'): @@ -1468,7 +1468,7 @@ def get_shell(): # cygwin has many problems with the shell setup # below, so i hardcoded everything here. if sys.platform == 'cygwin': - sh = "cygwin" + sh = "CYGWIN" shellname = "GNU Bash (Cygwin)" os.environ['SHELL'] = "/usr/bin/bash.exe" os.environ['OSTYPE'] = "cygwin" @@ -1481,7 +1481,7 @@ def get_shell(): sh = 'sh' os.environ['SHELL'] = sh - if windows and sh: + if WINDOWS and sh: sh = os.path.splitext(sh)[0] if sh == "ksh": @@ -1610,7 +1610,7 @@ def close_gui(): def clear_screen(): """Clear terminal""" - if windows: + if WINDOWS: pass # TODO: uncomment when PDCurses works. # cls @@ -1783,7 +1783,7 @@ def bash_startup(location, location_name, grass_env_file): for line in readfile(env_file).splitlines(): # Bug related to OS X "SIP", see # https://trac.osgeo.org/grass/ticket/3462#comment:13 - if macosx or not line.startswith('export'): + if MACOSX or not line.startswith('export'): f.write(line + '\n') f.write("export PATH=\"%s\"\n" % os.getenv('PATH')) @@ -1796,7 +1796,7 @@ def bash_startup(location, location_name, grass_env_file): def default_startup(location, location_name): - if windows: + if WINDOWS: os.environ['PS1'] = "GRASS %s> " % (grass_version) # "$ETC/run" doesn't work at all??? process = subprocess.Popen([os.getenv('SHELL')]) @@ -1896,7 +1896,7 @@ def print_params(): def get_username(): """Get name of the current user""" - if windows: + if WINDOWS: user = os.getenv('USERNAME') if not user: user = "user_name" From 906ff688af8aec501839740b3c83d15edfe0dff7 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 3 Feb 2019 23:58:14 +0200 Subject: [PATCH 09/22] lib/init/grass: Move the info message out of the "show_info()" function. This was messing up with the vim code folding. --- lib/init/grass.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 63408a69..a69706b2 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -1646,22 +1646,25 @@ def say_hello(): pass -def show_info(shellname, grass_gui, default_gui): - """Write basic info about GRASS GIS and GRASS session to stderr""" - sys.stderr.write( -r""" +INFO_TEXT = r"""\ %-41shttps://grass.osgeo.org %-41s%s (%s) %-41sg.manual -i %-41sg.version -c %-41sg.version -x -""" % (_("GRASS GIS homepage:"), +""" + + +def show_info(shellname, grass_gui, default_gui): + """Write basic info about GRASS GIS and GRASS session to stderr""" + sys.stderr.write(INFO_TEXT % ( + _("GRASS GIS homepage:"), # GTC Running through: SHELL NAME - _("This version running through:"), - shellname, os.getenv('SHELL'), - _("Help is available with the command:"), - _("See the licence terms with:"), - _("See citation options with:"))) + _("This version running through:"), + shellname, os.getenv('SHELL'), + _("Help is available with the command:"), + _("See the licence terms with:"), + _("See citation options with:"))) if grass_gui == 'wxpython': message("%-41sg.gui wxpython" % _("If required, restart the GUI with:")) From bb2d09ecc0e187109859ace869a91a3e9983e625 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 09:51:36 +0200 Subject: [PATCH 10/22] lib/init/grass: Remove unused constants --- lib/init/grass.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index a69706b2..9a0f539e 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -60,29 +60,17 @@ # for wxpath _WXPYTHON_BASE = None -# ----+- Python 3 compatibility start -+---- -PY2 = sys.version[0] == '2' ENCODING = locale.getdefaultlocale()[1] if ENCODING is None: ENCODING = 'UTF-8' print("Default locale not found, using UTF-8") # intentionally not translatable - +# Python 3 compatibility start +PY2 = sys.version[0] == '2' if PY2: string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str else: string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - MAXSIZE = sys.maxsize - -# ----+- Python 3 compatibility end -+---- # Variables substituted during build process if 'GISBASE' in os.environ: From 44ce2588e42b89a9d31716f5ceccfe0da9d58b4e Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 10:28:06 +0200 Subject: [PATCH 11/22] lib/init/grass: Use six for cross version Python compatibility Six is being pulled by matplotlib anyway, but for good measure, I also added it to the explicit requirements. This might require additional action on win/mac. --- .travis/linux.install.sh | 4 ++-- Dockerfile | 1 + REQUIREMENTS.html | 4 ++++ Vagrantfile | 1 + lib/init/grass.py | 14 ++++---------- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.travis/linux.install.sh b/.travis/linux.install.sh index 8f66263d..67cf3917 100755 --- a/.travis/linux.install.sh +++ b/.travis/linux.install.sh @@ -30,6 +30,7 @@ sudo apt-get install --no-install-recommends \ libxmu-dev \ python \ python-wxgtk3.0 \ + python-six \ python-dev \ unixodbc-dev \ libnetcdf-dev \ @@ -37,5 +38,4 @@ sudo apt-get install --no-install-recommends \ dpatch \ libblas-dev \ liblapack-dev \ - python-numpy - + python-numpy \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 6463bf93..1707fd95 100644 --- a/Dockerfile +++ b/Dockerfile @@ -55,6 +55,7 @@ RUN apt-get update \ python-pil \ python-ply \ python-requests \ + python-six \ sqlite3 \ subversion \ unixodbc-dev \ diff --git a/REQUIREMENTS.html b/REQUIREMENTS.html index dd0270df..49346b40 100644 --- a/REQUIREMENTS.html +++ b/REQUIREMENTS.html @@ -177,6 +177,10 @@

Optional requirements:

https://pypi.python.org/pypi/termcolor +
  • six (needed for cross-version Python compatibility)
    +https://pypi.python.org/pypi/six +
  • +
  • FFMPEG or alternative (for wxGUI Animation tool - g.gui.module), specifically ffmpeg tool
    http://ffmpeg.org diff --git a/Vagrantfile b/Vagrantfile index 5308421e..7fdb5484 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -71,6 +71,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| "python-numpy", "python-ply", "python-pil", + "python-six", "libnetcdf-dev", "netcdf-bin", "libblas-dev", diff --git a/lib/init/grass.py b/lib/init/grass.py index 9a0f539e..c6145a96 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -48,6 +48,7 @@ import subprocess import types import re +import six import platform import tempfile import locale @@ -65,13 +66,6 @@ ENCODING = 'UTF-8' print("Default locale not found, using UTF-8") # intentionally not translatable -# Python 3 compatibility start -PY2 = sys.version[0] == '2' -if PY2: - string_types = basestring, -else: - string_types = str, - # Variables substituted during build process if 'GISBASE' in os.environ: # TODO: should this be something like GRASS_PATH? @@ -161,7 +155,7 @@ def encode(string, encoding=ENCODING): # see https://trac.osgeo.org/grass/ticket/3508 def to_text_string(obj, encoding=ENCODING): """Convert `obj` to (unicode) text string""" - if PY2: + if six.PY2: # Python 2 return encode(obj, encoding=encoding) else: @@ -1544,11 +1538,11 @@ def run_batch_job(batch_job): :param batch_job: executable and parameters in a list or a string """ batch_job_string = batch_job - if not isinstance(batch_job, string_types): + if not isinstance(batch_job, six.string_types): # for messages only batch_job_string = ' '.join(batch_job) message(_("Executing <%s> ...") % batch_job_string) - if isinstance(batch_job, string_types): + if isinstance(batch_job, six.string_types): # shell=True is keeping the original GRASS_BATCH_JOB behavior def quote(string): if '"' in string: From 2c00830f893de979e6d2901af81752cfe70c4d71 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 10:33:32 +0200 Subject: [PATCH 12/22] lib/init/grass: Remove old comment The comment is from 2015. If there were problems, they would have surfaced since then. --- lib/init/grass.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index c6145a96..52958740 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -91,15 +91,6 @@ CYGWIN = "cygwin" in sys.platform MACOSX = "darwin" in sys.platform -# TODO: it is OK to remove this? -# at the beginning of this file were are happily getting GISBASE -# from the environment and we don't care about inconsistencies it might cause -# The following was commented out because of breaking winGRASS -# if 'GISBASE' in os.environ: -# sys.exit(_("ERROR: GRASS GIS is already running " -# "(environmental variable GISBASE found)")) -# this is not really an issue, we should be able to overpower another session - # Set GISBASE os.environ['GISBASE'] = gisbase From d2ab2c2e2f4c27824a4084811af218c8bf153747 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 10:34:01 +0200 Subject: [PATCH 13/22] lib/init/grass: Move all the gisbase stuff in a single place. --- lib/init/grass.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 52958740..de17faa4 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -74,8 +74,10 @@ # GRASS in that, we want to overwrite the settings, not to take it # possibly same for GRASS_PROJSHARE and others but maybe not gisbase = os.environ['GISBASE'] + gisbase = os.path.normpath(gisbase) else: gisbase = "@GISBASE@" + os.environ['GISBASE'] = gisbase cmd_name = "@START_UP@" grass_version = "@GRASS_VERSION_NUMBER@" ld_library_path_var = '@LD_LIBRARY_PATH_VAR@' @@ -84,16 +86,12 @@ else: config_projshare = "@CONFIG_PROJSHARE@" -gisbase = os.path.normpath(gisbase) # Get the system name WINDOWS = sys.platform == 'win32' CYGWIN = "cygwin" in sys.platform MACOSX = "darwin" in sys.platform -# Set GISBASE -os.environ['GISBASE'] = gisbase - # i18N # TODO: is this needed or even desirable when we have set_language()? gettext.install('grasslibs', os.path.join(gisbase, 'locale')) From 7e737ee7fec4b55cbb4aadf2021db4285a1809ac Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 10:39:47 +0200 Subject: [PATCH 14/22] lib/init/grass: Clarify comment. --- lib/init/grass.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index de17faa4..8a4c19fb 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -93,7 +93,10 @@ MACOSX = "darwin" in sys.platform # i18N -# TODO: is this needed or even desirable when we have set_language()? +# Calling gettext.install() is required since it installs _() in the builtins namespace +# https://docs.python.org/2/library/gettext.html#gettext.install +# If we remove it, we are going to be getting NameErrors when we define e.g. `HELP_TEXT` +# gettext.install('grasslibs', os.path.join(gisbase, 'locale')) From e5d0b3134bcee0d6d5a59f204f7cd6dd65b5ac5c Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 10:44:00 +0200 Subject: [PATCH 15/22] lib/init/grass: Capitalize all constants - GISBASE - CMD_NAME - GRASS_VERSION - LD_LIBRARY_PATH --- lib/init/grass.py | 60 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 8a4c19fb..e9f63b49 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -73,18 +73,18 @@ # setting it up, possible scenario: existing runtime and starting # GRASS in that, we want to overwrite the settings, not to take it # possibly same for GRASS_PROJSHARE and others but maybe not - gisbase = os.environ['GISBASE'] - gisbase = os.path.normpath(gisbase) + GISBASE = os.environ['GISBASE'] + GISBASE = os.path.normpath(GISBASE) else: - gisbase = "@GISBASE@" - os.environ['GISBASE'] = gisbase -cmd_name = "@START_UP@" -grass_version = "@GRASS_VERSION_NUMBER@" -ld_library_path_var = '@LD_LIBRARY_PATH_VAR@' + GISBASE = "@GISBASE@" + os.environ['GISBASE'] = GISBASE +CMD_NAME = "@START_UP@" +GRASS_VERSION = "@GRASS_VERSION_NUMBER@" +LD_LIBRARY_PATH_VAR = '@LD_LIBRARY_PATH_VAR@' if 'GRASS_PROJSHARE' in os.environ: - config_projshare = os.environ['GRASS_PROJSHARE'] + CONFIG_PROJSHARE = os.environ['GRASS_PROJSHARE'] else: - config_projshare = "@CONFIG_PROJSHARE@" + CONFIG_PROJSHARE = "@CONFIG_PROJSHARE@" # Get the system name @@ -97,7 +97,7 @@ # https://docs.python.org/2/library/gettext.html#gettext.install # If we remove it, we are going to be getting NameErrors when we define e.g. `HELP_TEXT` # -gettext.install('grasslibs', os.path.join(gisbase, 'locale')) +gettext.install('grasslibs', os.path.join(GISBASE, 'locale')) def decode(bytes_, encoding=ENCODING): @@ -246,22 +246,22 @@ def Popen(cmd, **kwargs): # pylint: disable=C0103 def gpath(*args): """Costruct path to file or directory in GRASS GIS installation - Can be called only after gisbase was set. + Can be called only after GISBASE was set. """ - return os.path.join(gisbase, *args) + return os.path.join(GISBASE, *args) def wxpath(*args): """Costruct path to file or directory in GRASS wxGUI - Can be called only after gisbase was set. + Can be called only after GISBASE was set. This function does not check if the directories exist or if GUI works this must be done by the caller if needed. """ global _WXPYTHON_BASE if not _WXPYTHON_BASE: - # this can be called only after gisbase was set + # this can be called only after GISBASE was set _WXPYTHON_BASE = gpath("gui", "wxpython") return os.path.join(_WXPYTHON_BASE, *args) @@ -358,8 +358,8 @@ def wxpath(*args): def help_message(default_gui): t = string.Template(HELP_TEXT) - s = t.substitute(CMD_NAME=cmd_name, DEFAULT_GUI=default_gui, - VERSION_NUMBER=grass_version) + s = t.substitute(CMD_NAME=CMD_NAME, DEFAULT_GUI=default_gui, + VERSION_NUMBER=GRASS_VERSION) sys.stderr.write(s) @@ -628,7 +628,7 @@ def set_paths(grass_config_dir): # Set LD_LIBRARY_PATH (etc) to find GRASS shared libraries # this works for subprocesses but won't affect the current process - path_prepend(gpath("lib"), ld_library_path_var) + path_prepend(gpath("lib"), LD_LIBRARY_PATH_VAR) def find_exe(pgm): @@ -665,7 +665,7 @@ def set_defaults(): # GRASS_PROJSHARE if not os.getenv('GRASS_PROJSHARE'): - os.environ['GRASS_PROJSHARE'] = config_projshare + os.environ['GRASS_PROJSHARE'] = CONFIG_PROJSHARE def set_display_defaults(): @@ -1091,7 +1091,7 @@ def gui_startup(grass_gui): "Use '--help' for further options\n" " {cmd_name} --help\n" "See also: https://grass.osgeo.org/{cmd_name}/manuals/helptext.html").format( - cmd_name=cmd_name)) + cmd_name=CMD_NAME)) elif ret == 5: # defined in gui/wxpython/gis_set.py # User wants to exit from GRASS message(_("Exit was requested in GUI.\nGRASS GIS will not start. Bye.")) @@ -1607,8 +1607,8 @@ def show_banner(): def say_hello(): """Write welcome to stderr including Subversion revision if in svn copy""" - sys.stderr.write(_("Welcome to GRASS GIS %s") % grass_version) - if grass_version.endswith('svn'): + sys.stderr.write(_("Welcome to GRASS GIS %s") % GRASS_VERSION) + if GRASS_VERSION.endswith('svn'): try: filerev = open(gpath('etc', 'VERSIONNUMBER')) linerev = filerev.readline().rstrip('\n') @@ -1667,7 +1667,7 @@ def csh_startup(location, location_name, mapset, grass_env_file): f.write("set prompt = '\\\n") f.write("Mapset <%s> in Location <%s> \\\n" % (mapset, location_name)) - f.write("GRASS GIS %s > '\n" % grass_version) + f.write("GRASS GIS %s > '\n" % GRASS_VERSION) f.write("set BOGUS=``;unset BOGUS\n") # csh shell rc file left for backward compatibility @@ -1724,7 +1724,7 @@ def bash_startup(location, location_name, grass_env_file): else: grass_name = "GRASS" f.write("PS1='{name} {version} ({location}):\\w > '\n".format( - name=grass_name, version=grass_version, location=location_name)) + name=grass_name, version=GRASS_VERSION, location=location_name)) # TODO: have a function and/or module to test this mask2d_test = 'test -f "$MAPSET_PATH/cell/MASK"' @@ -1774,11 +1774,11 @@ def bash_startup(location, location_name, grass_env_file): def default_startup(location, location_name): if WINDOWS: - os.environ['PS1'] = "GRASS %s> " % (grass_version) + os.environ['PS1'] = "GRASS %s> " % (GRASS_VERSION) # "$ETC/run" doesn't work at all??? process = subprocess.Popen([os.getenv('SHELL')]) else: - os.environ['PS1'] = "GRASS %s (%s):\\w > " % (grass_version, location_name) + os.environ['PS1'] = "GRASS %s (%s):\\w > " % (GRASS_VERSION, location_name) process = Popen([gpath("etc", "run"), os.getenv('SHELL')]) return process @@ -1835,7 +1835,7 @@ def print_params(): for arg in params: if arg == 'path': - sys.stdout.write("%s\n" % gisbase) + sys.stdout.write("%s\n" % GISBASE) elif arg == 'arch': val = grep('ARCH', linesplat) sys.stdout.write("%s\n" % val[0].split('=')[1].strip()) @@ -1866,7 +1866,7 @@ def print_params(): except: sys.stdout.write("No SVN revision defined\n") elif arg == 'version': - sys.stdout.write("%s\n" % grass_version) + sys.stdout.write("%s\n" % GRASS_VERSION) else: message(_("Parameter <%s> not supported") % arg) @@ -1917,7 +1917,7 @@ def parse_cmdline(argv, default_gui): for i in argv: # Check if the user asked for the version if i in ["-v", "--version"]: - message("GRASS GIS %s" % grass_version) + message("GRASS GIS %s" % GRASS_VERSION) message('\n' + readfile(gpath("etc", "license"))) sys.exit() # Check if the user asked for help @@ -1979,7 +1979,7 @@ def main(): # Set GRASS version number for R interface etc # (must be an env var for MS Windows) - os.environ['GRASS_VERSION'] = grass_version + os.environ['GRASS_VERSION'] = GRASS_VERSION # Set the GIS_LOCK variable to current process id gis_lock = str(os.getpid()) @@ -2074,7 +2074,7 @@ def main(): " - Use '--help' for further options\n" " {cmd_name} --help\n" "See also: https://grass.osgeo.org/{cmd_name}/manuals/helptext.html").format( - cmd_name=cmd_name, gisrcrc=gisrcrc)) + cmd_name=CMD_NAME, gisrcrc=gisrcrc)) create_initial_gisrc(gisrc) message(_("Starting GRASS GIS...")) From d84f4c4c07fdeaae80b17df53b44f39a2b340458 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 10:44:19 +0200 Subject: [PATCH 16/22] lib/init/grass: Fix typo --- lib/init/grass.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index e9f63b49..41d52be7 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -1145,11 +1145,11 @@ def load_gisrc(gisrc, gisrcrc): mapset_settings.mapset = kv.get('MAPSET') if not mapset_settings.is_valid(): fatal(_("Error reading data path information from g.gisenv.\n" - "GISDBASE={gisbase}\n" + "GISDBASE={gisdbase}\n" "LOCATION_NAME={location}\n" "MAPSET={mapset}\n\n" "Check the <{file}> file.").format( - gisbase=mapset_settings.gisdbase, + gisdbase=mapset_settings.gisdbase, location=mapset_settings.location, mapset=mapset_settings.mapset, file=gisrcrc)) From 6689f1525fd8c3ac2d39f2dec5c067c41787c3ff Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 10:56:13 +0200 Subject: [PATCH 17/22] lib/init/grass: Simplify setting a value to CONFIG_PROJSHARE --- lib/init/grass.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 41d52be7..04ccb7b9 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -81,11 +81,7 @@ CMD_NAME = "@START_UP@" GRASS_VERSION = "@GRASS_VERSION_NUMBER@" LD_LIBRARY_PATH_VAR = '@LD_LIBRARY_PATH_VAR@' -if 'GRASS_PROJSHARE' in os.environ: - CONFIG_PROJSHARE = os.environ['GRASS_PROJSHARE'] -else: - CONFIG_PROJSHARE = "@CONFIG_PROJSHARE@" - +CONFIG_PROJSHARE = os.environ.get('GRASS_PROJSHARE', "@CONFIG_PROJSHARE@") # Get the system name WINDOWS = sys.platform == 'win32' From 5682b166936ec0bd1e07b42f03ef11edb4e3811b Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 11:50:23 +0200 Subject: [PATCH 18/22] lib/init/grass: Add comments about GISBASE --- lib/init/grass.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 04ccb7b9..3f9fd229 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -66,17 +66,24 @@ ENCODING = 'UTF-8' print("Default locale not found, using UTF-8") # intentionally not translatable -# Variables substituted during build process +# The "@...@" variables are being substituted during build process +# +# TODO: should GISBASE be renamed to something like GRASS_PATH? +# GISBASE marks complete runtime, so no need to get it here when +# setting it up, possible scenario: existing runtime and starting +# GRASS in that, we want to overwrite the settings, not to take it +# possibly same for GRASS_PROJSHARE and others but maybe not +# +# We need to simultaneously make sure that: +# - we get GISBASE from os.environ if it is defined (doesn't this mean that we are already +# inside a GRASS session? If we are, why do we need to run this script again???). +# - GISBASE exists as an ENV variable +# +# pmav99: Ugly as hell, but that's what the code before the refactoring was doing. if 'GISBASE' in os.environ: - # TODO: should this be something like GRASS_PATH? - # GISBASE marks complete runtime, so no need to get it here when - # setting it up, possible scenario: existing runtime and starting - # GRASS in that, we want to overwrite the settings, not to take it - # possibly same for GRASS_PROJSHARE and others but maybe not - GISBASE = os.environ['GISBASE'] - GISBASE = os.path.normpath(GISBASE) + GISBASE = os.path.normpath(os.environ["GISBASE"]) else: - GISBASE = "@GISBASE@" + GISBASE = os.path.normpath("@GISBASE@") os.environ['GISBASE'] = GISBASE CMD_NAME = "@START_UP@" GRASS_VERSION = "@GRASS_VERSION_NUMBER@" From 070f9e185499838a4a61e6afec0b0a8697638ed9 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Mon, 4 Feb 2019 20:30:29 +0200 Subject: [PATCH 19/22] lib/init/grass: Validate cmdline in a separate function --- lib/init/grass.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 3f9fd229..463c52b4 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -1966,6 +1966,26 @@ def parse_cmdline(argv, default_gui): return params +def validate_cmdline(params): + """ Validate the cmdline params and exit if necessary. """ + if params.exit_grass and not params.create_new: + fatal(_("Flag -e requires also flag -c")) + if params.tmp_location and not params.geofile: + fatal( + _( + "Coordinate reference system argument (e.g. EPSG)" + " is needed for --tmp-location" + ) + ) + if params.tmp_location and params.mapset: + fatal( + _( + "Only one argument (e.g. EPSG) is needed for" + " --tmp-location, mapset name <{}> provided" + ).format(params.mapset) + ) + + def main(): """The main function which does the whole setup and run procedure @@ -2002,15 +2022,7 @@ def main(): params = parse_cmdline(clean_argv, default_gui=default_gui) except ValueError: params = parse_cmdline(sys.argv[1:], default_gui=default_gui) - if params.exit_grass and not params.create_new: - fatal(_("Flag -e requires also flag -c")) - if params.tmp_location and not params.geofile: - fatal(_("Coordinate reference system argument (e.g. EPSG)" - " is needed for --tmp-location")) - if params.tmp_location and params.mapset: - fatal(_("Only one argument (e.g. EPSG) is needed for" - " --tmp-location, mapset name <{}> provided").format( - params.mapset)) + validate_cmdline(params) # For now, we allow, but not advertise/document, --tmp-location # without --exec (usefulness to be evaluated). From 520f4df45297f5e83b943d902c213323b0dfdeb3 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 24 Feb 2019 02:31:10 +0200 Subject: [PATCH 20/22] lib/init/grass: Inline variable substitution inside "help_message()" The main motivation here is to avoid making "_()" calls at the module level which will hopefully let us remove the early "gettext.install()" call in a later commit. --- lib/init/grass.py | 78 ++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 463c52b4..282f4eac 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -320,47 +320,49 @@ def wxpath(*args): GRASS_ADDON_BASE {addon_base_var} GRASS_BATCH_JOB {batch_var} GRASS_PYTHON {python_var} -""".format( - usage=_("Usage"), - flags=_("Flags"), - help_flag=_("print this help message"), - version_flag=_("show version information and exit"), - create=_("create given database, location or mapset if it doesn't exist"), - exit_after=_("exit after creation of location or mapset. Only with -c flag"), - force_removal=_("force removal of .gislock if exists (use with care!). Only with --text flag"), - text=_("use text based interface (skip graphical welcome screen)"), - text_detail=_("and set as default"), - gtext=_("use text based interface (show graphical welcome screen)"), - gtext_detail=_("and set as default"), - gui=_("use $DEFAULT_GUI graphical user interface"), - gui_detail=_("and set as default"), - config=_("print GRASS configuration parameters"), - config_detail=_("options: arch,build,compiler,path,revision,svn_revision,version"), - params=_("Parameters"), - gisdbase=_("initial GRASS database directory"), - gisdbase_detail=_("directory containing Locations"), - location=_("initial GRASS Location"), - location_detail=_("directory containing Mapsets with one common coordinate system (projection)"), - mapset=_("initial GRASS Mapset"), - full_mapset=_("fully qualified initial Mapset directory"), - env_vars=_("Environment variables relevant for startup"), - gui_var=_("select GUI (text, gui, gtext)"), - html_var=_("set html web browser for help pages"), - addon_path_var=_("set additional path(s) to local GRASS modules or user scripts"), - addon_base_var=_("set additional GISBASE for locally installed GRASS Addons"), - batch_var=_("shell script to be processed as batch job"), - python_var=_("set Python interpreter name to override 'python'"), - exec_=_("execute GRASS module or script"), - exec_detail=_("provided executable will be executed in GRASS session"), - executable=_("GRASS module, script or any other executable"), - executable_params=_("parameters of the executable"), - standard_flags=_("standard flags"), - tmp_location=_("create temporary location (use with the --exec flag)"), - ) +""" def help_message(default_gui): - t = string.Template(HELP_TEXT) + t = string.Template( + HELP_TEXT.format( + usage=_("Usage"), + flags=_("Flags"), + help_flag=_("print this help message"), + version_flag=_("show version information and exit"), + create=_("create given database, location or mapset if it doesn't exist"), + exit_after=_("exit after creation of location or mapset. Only with -c flag"), + force_removal=_("force removal of .gislock if exists (use with care!). Only with --text flag"), + text=_("use text based interface (skip graphical welcome screen)"), + text_detail=_("and set as default"), + gtext=_("use text based interface (show graphical welcome screen)"), + gtext_detail=_("and set as default"), + gui=_("use $DEFAULT_GUI graphical user interface"), + gui_detail=_("and set as default"), + config=_("print GRASS configuration parameters"), + config_detail=_("options: arch,build,compiler,path,revision,svn_revision,version"), + params=_("Parameters"), + gisdbase=_("initial GRASS database directory"), + gisdbase_detail=_("directory containing Locations"), + location=_("initial GRASS Location"), + location_detail=_("directory containing Mapsets with one common coordinate system (projection)"), + mapset=_("initial GRASS Mapset"), + full_mapset=_("fully qualified initial Mapset directory"), + env_vars=_("Environment variables relevant for startup"), + gui_var=_("select GUI (text, gui, gtext)"), + html_var=_("set html web browser for help pages"), + addon_path_var=_("set additional path(s) to local GRASS modules or user scripts"), + addon_base_var=_("set additional GISBASE for locally installed GRASS Addons"), + batch_var=_("shell script to be processed as batch job"), + python_var=_("set Python interpreter name to override 'python'"), + exec_=_("execute GRASS module or script"), + exec_detail=_("provided executable will be executed in GRASS session"), + executable=_("GRASS module, script or any other executable"), + executable_params=_("parameters of the executable"), + standard_flags=_("standard flags"), + tmp_location=_("create temporary location (use with the --exec flag)"), + ) + ) s = t.substitute(CMD_NAME=CMD_NAME, DEFAULT_GUI=default_gui, VERSION_NUMBER=GRASS_VERSION) sys.stderr.write(s) From 7229f5f7baf1d30299b368d63e9d4e7a67decaee Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 24 Feb 2019 03:13:13 +0200 Subject: [PATCH 21/22] lib/init/grass: Ensure that the init process only happens inside main() With this commit: 1. we remove the "gettext.install()" call from the module level 2. we make sure that "set_language()" is the first step of the init process. --- lib/init/grass.py | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 282f4eac..26651c34 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -95,13 +95,6 @@ CYGWIN = "cygwin" in sys.platform MACOSX = "darwin" in sys.platform -# i18N -# Calling gettext.install() is required since it installs _() in the builtins namespace -# https://docs.python.org/2/library/gettext.html#gettext.install -# If we remove it, we are going to be getting NameErrors when we define e.g. `HELP_TEXT` -# -gettext.install('grasslibs', os.path.join(GISBASE, 'locale')) - def decode(bytes_, encoding=ENCODING): """Decode bytes with default locale and return (unicode) string @@ -1993,6 +1986,13 @@ def main(): Only few things are set on the module level. """ + # Set language + # This has to be called before any _() function call! + # Subsequent functions are using _() calls and + # thus must be called only after Language has been set. + grass_config_dir = get_grass_config_dir() + set_language(grass_config_dir) + # Set default GUI default_gui = "wxpython" @@ -2010,8 +2010,6 @@ def main(): gis_lock = str(os.getpid()) os.environ['GIS_LOCK'] = gis_lock - grass_config_dir = get_grass_config_dir() - batch_job = get_batch_job_from_env_variable() # Parse the command-line options and set several global variables @@ -2038,13 +2036,6 @@ def main(): # Set the username user = get_username() - # TODO: this might need to be moved before processing of parameters - # and getting batch job - # Set language - # This has to be called before any _() function call! - # Subsequent functions are using _() calls and - # thus must be called only after Language has been set. - set_language(grass_config_dir) # Set shell (needs to be called before load_env()) sh, shellname = get_shell() From 18096115e81b96746c4c9730f481e36747759325 Mon Sep 17 00:00:00 2001 From: Panos Mavrogiorgos Date: Sun, 24 Feb 2019 02:48:24 +0200 Subject: [PATCH 22/22] lib/init/grass: Refuse to start if ~/.grass7 exists but is not a directory --- lib/init/grass.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/init/grass.py b/lib/init/grass.py index 26651c34..e0ec20d0 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -40,6 +40,7 @@ from __future__ import print_function import sys import os +import errno import atexit import gettext import shutil @@ -384,12 +385,12 @@ def get_grass_config_dir(): else: grass_config_dirname = ".grass7" directory = os.path.join(os.getenv('HOME'), grass_config_dirname) - if not os.path.exists(directory): + if not os.path.isdir(directory) : try: os.mkdir(directory) except OSError as e: # Can happen as a race condition - if not e.errno == 17: + if not e.errno == errno.EEXIST or not os.path.isdir(directory): fatal( _("Failed to create configuration directory '%s' with error: %s") % (directory, e.strerror))