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 bfca4dc4..e0ec20d0 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:
+ 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:
- # 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:
@@ -1633,7 +1583,7 @@ def close_gui():
def clear_screen():
"""Clear terminal"""
- if windows:
+ if WINDOWS:
pass
# TODO: uncomment when PDCurses works.
# cls
@@ -1656,8 +1606,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')
@@ -1669,22 +1619,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:"))
@@ -1713,7 +1666,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
@@ -1770,7 +1723,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"'
@@ -1806,7 +1759,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'))
@@ -1819,12 +1772,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
@@ -1853,7 +1806,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):
@@ -1881,7 +1834,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())
@@ -1912,14 +1865,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"
@@ -1963,7 +1916,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
@@ -2009,24 +1962,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():
@@ -2034,6 +1987,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"
@@ -2045,14 +2005,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
@@ -2065,15 +2023,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).
@@ -2087,13 +2037,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()
@@ -2106,10 +2049,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)
@@ -2141,7 +2083,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..."))