diff --git a/REQUIREMENTS.html b/REQUIREMENTS.html index 3ad99a8e46c..4410b3d9ae7 100644 --- a/REQUIREMENTS.html +++ b/REQUIREMENTS.html @@ -185,6 +185,10 @@

Optional packages:

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 5f98e30cd7d..4be126b572c 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 1a2db1f00a5..dd62c7277bc 100644 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -40,48 +40,85 @@ from __future__ import print_function import sys import os +import errno import atexit +import gettext +import shutil +import signal import string import subprocess +import types import re +import six import platform import tempfile import locale -# ----+- Python 3 compatibility start -+---- -PY2 = sys.version[0] == '2' +# mechanism meant for debugging this script (only) +# private global to store if we are debugging +_DEBUG = None + +# for wxpath +_WXPYTHON_BASE = None + ENCODING = locale.getdefaultlocale()[1] if ENCODING is None: ENCODING = 'UTF-8' print("Default locale not found, using UTF-8") # intentionally not translatable +# 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 and len(os.getenv('GISBASE')) > 0: + GISBASE = os.path.normpath(os.environ["GISBASE"]) +else: + GISBASE = os.path.normpath("@GISBASE@") + os.environ['GISBASE'] = GISBASE +CMD_NAME = "@START_UP@" +GRASS_VERSION = "@GRASS_VERSION_NUMBER@" +LD_LIBRARY_PATH_VAR = '@LD_LIBRARY_PATH_VAR@' +CONFIG_PROJSHARE = os.environ.get('GRASS_PROJSHARE', "@CONFIG_PROJSHARE@") + +# Get the system name +WINDOWS = sys.platform == 'win32' +CYGWIN = "cygwin" in sys.platform +MACOSX = "darwin" in sys.platform + -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 @@ -89,7 +126,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 @@ -97,20 +135,16 @@ 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") -# 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: + if six.PY2: # Python 2 return encode(obj, encoding=encoding) else: @@ -118,53 +152,6 @@ def to_text_string(obj, encoding=ENCODING): return decode(obj, encoding=encoding) -if PY2: - import types - 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 and len(os.getenv('GISBASE')) > 0: - # 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 -import gettext -# 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) - - def try_remove(path): try: os.remove(path) @@ -172,65 +159,17 @@ def try_remove(path): pass -def try_rmdir(path): - try: - os.rmdir(path) - except: - 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) -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...")) - - -def message(msg): - sys.stderr.write(msg + "\n") - 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,6 +197,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') @@ -275,14 +228,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) @@ -290,33 +243,29 @@ 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) - - -# for wxpath -_WXPYTHON_BASE = None + 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) # 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}: @@ -365,49 +314,51 @@ 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) - s = t.substitute(CMD_NAME=cmd_name, DEFAULT_GUI=default_gui, - VERSION_NUMBER=grass_version) + 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) @@ -434,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)) @@ -629,12 +580,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') @@ -676,7 +627,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): @@ -694,7 +645,7 @@ def set_defaults(): pager = "more" elif find_exe("less"): pager = "less" - elif windows: + elif WINDOWS: pager = "more" else: pager = "cat" @@ -702,7 +653,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" @@ -713,7 +664,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(): @@ -728,15 +679,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 @@ -748,7 +699,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 @@ -763,7 +714,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')) @@ -780,7 +731,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') @@ -1139,7 +1090,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.")) @@ -1193,11 +1144,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)) @@ -1481,7 +1432,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'): @@ -1490,7 +1441,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" @@ -1503,7 +1454,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": @@ -1578,11 +1529,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: @@ -1622,7 +1573,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: @@ -1645,8 +1595,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') @@ -1658,22 +1608,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:")) @@ -1702,7 +1655,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 @@ -1758,8 +1711,8 @@ def bash_startup(location, location_name, grass_env_file): grass_name = "ISIS-GRASS" else: grass_name = "GRASS" - f.write("PS1='{name} {version} ({location}):\\W > '\n".format( - name=grass_name, version=grass_version, location=location_name)) + f.write("PS1='{name} {version} ({location}):\\w > '\n".format( + 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"' @@ -1795,7 +1748,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')) @@ -1808,12 +1761,12 @@ def bash_startup(location, location_name, grass_env_file): def default_startup(location, location_name): - if windows: - os.environ['PS1'] = "GRASS %s> " % (grass_version) + if WINDOWS: + 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 @@ -1842,7 +1795,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): @@ -1870,7 +1823,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()) @@ -1901,14 +1854,14 @@ 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) def get_username(): """Get name of the current user""" - if windows: + if WINDOWS: user = os.getenv('USERNAME') if not user: user = "user_name" @@ -1952,7 +1905,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 @@ -1998,24 +1951,24 @@ 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 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(): @@ -2023,6 +1976,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" @@ -2034,14 +1994,12 @@ 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()) 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 @@ -2054,15 +2012,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). @@ -2076,13 +2026,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() @@ -2095,10 +2038,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) @@ -2130,7 +2072,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..."))