diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index 8e8ad1730e6..390010ae5e0 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -12,6 +12,7 @@ jobs: strategy: matrix: directory: + - lib/init - scripts fail-fast: false diff --git a/lib/init/grass.py b/lib/init/grass.py index 917b8ec5c66..5b33dba0e62 100755 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -67,7 +67,7 @@ ENCODING = locale.getdefaultlocale()[1] if ENCODING is None: - ENCODING = 'UTF-8' + ENCODING = "UTF-8" print("Default locale not found, using UTF-8") # intentionally not translatable # The "@...@" variables are being substituted during build process @@ -84,18 +84,18 @@ # - 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: +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 + 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@") +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' +WINDOWS = sys.platform == "win32" CYGWIN = "cygwin" in sys.platform MACOSX = "darwin" in sys.platform @@ -163,11 +163,11 @@ def try_remove(path): def clean_env(): - gisrc = os.environ['GISRC'] + 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'): + if k.endswith("PID") or k.startswith("MONITOR"): continue env_new[k] = v write_gisrc(env_new, gisrc) @@ -181,7 +181,7 @@ def is_debug(): global _DEBUG if _DEBUG is not None: return _DEBUG - _DEBUG = os.getenv('GRASS_DEBUG') + _DEBUG = os.getenv("GRASS_DEBUG") # translate to bool (no or empty variable means false) if _DEBUG: _DEBUG = True @@ -206,17 +206,17 @@ def message(msg): def warning(text): - sys.stderr.write(_("WARNING") + ': ' + text + os.linesep) + sys.stderr.write(_("WARNING") + ": " + text + os.linesep) def fatal(msg): - sys.stderr.write("%s: " % _('ERROR') + msg + os.linesep) + sys.stderr.write("%s: " % _("ERROR") + msg + os.linesep) sys.exit(_("Exiting...")) def readfile(path): debug("Reading %s" % path) - f = open(path, 'r') + f = open(path, "r") s = f.read() f.close() return s @@ -224,7 +224,7 @@ def readfile(path): def writefile(path, s): debug("Writing %s" % path) - f = open(path, 'w') + f = open(path, "w") f.write(s) f.close() @@ -232,14 +232,14 @@ def writefile(path, s): def call(cmd, **kwargs): """Wrapper for subprocess.call to deal with platform-specific issues""" if WINDOWS: - kwargs['shell'] = True + 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: - kwargs['shell'] = True + kwargs["shell"] = True return subprocess.Popen(cmd, **kwargs) @@ -271,8 +271,10 @@ def count_wide_chars(s): :param str s: string """ - return sum(unicodedata.east_asian_width(c) in 'WF' for c in - (s if sys.version_info.major >= 3 else unicode(s))) + return sum( + unicodedata.east_asian_width(c) in "WF" + for c in (s if sys.version_info.major >= 3 else unicode(s)) + ) def f(fmt, *args): @@ -284,21 +286,23 @@ def f(fmt, *args): """ matches = [] # https://docs.python.org/3/library/stdtypes.html#old-string-formatting - for m in re.finditer('%([#0 +-]*)([0-9]*)(\.[0-9]*)?([hlL]?[diouxXeEfFgGcrsa%])', fmt): + for m in re.finditer( + "%([#0 +-]*)([0-9]*)(\.[0-9]*)?([hlL]?[diouxXeEfFgGcrsa%])", fmt + ): matches.append(m) if len(matches) != len(args): - raise Exception('The numbers of format specifiers and arguments do not match') + raise Exception("The numbers of format specifiers and arguments do not match") i = len(args) - 1 for m in reversed(matches): f = m.group(1) w = m.group(2) - p = m.group(3) or '' + p = m.group(3) or "" c = m.group(4) - if c == 's' and w: + if c == "s" and w: w = str(int(w) - count_wide_chars(args[i])) - fmt = ''.join((fmt[:m.start()], '%', f, w, p, c, fmt[m.end():])) + fmt = "".join((fmt[: m.start()], "%", f, w, p, c, fmt[m.end() :])) i -= 1 return fmt % args @@ -368,8 +372,12 @@ def help_message(default_gui): 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"), + 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)"), @@ -377,19 +385,27 @@ def help_message(default_gui): gui=_("use $DEFAULT_GUI graphical user interface"), gui_detail=_("and set as default"), config=_("print GRASS configuration parameters"), - config_detail=_("options: arch,build,compiler,date,path,revision,svn_revision,version"), + config_detail=_( + "options: arch,build,compiler,date,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)"), + 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"), + 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" + ), 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"), @@ -397,13 +413,18 @@ def help_message(default_gui): executable_params=_("parameters of the executable"), standard_flags=_("standard flags"), tmp_location=_("create temporary location (use with the --exec flag)"), - tmp_location_detail=_("created in a temporary directory and deleted at exit"), + tmp_location_detail=_( + "created in a temporary directory and deleted at exit" + ), tmp_mapset=_("create temporary mapset (use with the --exec flag)"), - tmp_mapset_detail=_("created in the specified location and deleted at exit"), + tmp_mapset_detail=_( + "created in the specified location and deleted at exit" + ), ) ) - 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) @@ -416,20 +437,28 @@ def get_grass_config_dir(): Configuration directory is for example used for grass env file (the one which caries mapset settings from session to session). """ - if sys.platform == 'win32': + if sys.platform == "win32": grass_config_dirname = "GRASS7" - win_conf_path = os.getenv('APPDATA') + win_conf_path = os.getenv("APPDATA") # this can happen with some strange settings if not win_conf_path: - fatal(_("The APPDATA variable is not set, ask your operating" - " system support")) + fatal( + _( + "The APPDATA variable is not set, ask your operating" + " system support" + ) + ) if not os.path.exists(win_conf_path): - fatal(_("The APPDATA variable points to directory which does" - " not exist, ask your operating system support")) + fatal( + _( + "The APPDATA variable points to directory which does" + " not exist, ask your operating system support" + ) + ) directory = os.path.join(win_conf_path, grass_config_dirname) else: grass_config_dirname = ".grass7" - directory = os.path.join(os.getenv('HOME'), grass_config_dirname) + directory = os.path.join(os.getenv("HOME"), grass_config_dirname) if not os.path.isdir(directory): try: os.mkdir(directory) @@ -438,7 +467,8 @@ def get_grass_config_dir(): 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)) + % (directory, e.strerror) + ) return directory @@ -449,18 +479,18 @@ def create_tmp(user, gis_lock): :param gis_lock: session lock filename to be used in the directory name """ # use $TMPDIR if it exists, then $TEMP, otherwise /tmp - tmp = os.getenv('TMPDIR') + tmp = os.getenv("TMPDIR") if not tmp: - tmp = os.getenv('TEMP') + tmp = os.getenv("TEMP") if not tmp: - tmp = os.getenv('TMP') + tmp = os.getenv("TMP") if not tmp: tmp = tempfile.gettempdir() if tmp: tmpdir = os.path.join( - tmp, "grass7-%(user)s-%(lock)s" % {'user': user, - 'lock': gis_lock}) + tmp, "grass7-%(user)s-%(lock)s" % {"user": user, "lock": gis_lock} + ) try: os.mkdir(tmpdir, 0o700) except: @@ -470,8 +500,8 @@ def create_tmp(user, gis_lock): for ttmp in ("/tmp", "/var/tmp", "/usr/tmp"): tmp = ttmp tmpdir = os.path.join( - tmp, "grass7-%(user)s-%(lock)s" % {'user': user, - 'lock': gis_lock}) + tmp, "grass7-%(user)s-%(lock)s" % {"user": user, "lock": gis_lock} + ) try: os.mkdir(tmpdir, 0o700) except: @@ -480,14 +510,22 @@ def create_tmp(user, gis_lock): break if not tmp: - fatal(_("Unable to create temporary directory ! Exiting.") % {'user': user, 'lock': gis_lock}) + fatal( + _( + "Unable to create temporary directory ! Exiting." + ) + % {"user": user, "lock": gis_lock} + ) # promoting the variable even if it was not defined before - os.environ['TMPDIR'] = tmpdir + os.environ["TMPDIR"] = tmpdir - debug("Tmp directory '{tmpdir}' created for user '{user}'".format( - tmpdir=tmpdir, user=user)) + debug( + "Tmp directory '{tmpdir}' created for user '{user}'".format( + tmpdir=tmpdir, user=user + ) + ) return tmpdir @@ -506,7 +544,7 @@ def get_gisrc_from_config_dir(grass_config_dir, batch_job): def create_gisrc(tmpdir, gisrcrc): # Set the session grassrc file gisrc = os.path.join(tmpdir, "gisrc") - os.environ['GISRC'] = gisrc + os.environ["GISRC"] = gisrc # remove invalid GISRC file to avoid disturbing error messages: try: @@ -526,17 +564,19 @@ def create_gisrc(tmpdir, gisrcrc): def read_gisrc(filename): kv = {} try: - f = open(filename, 'r') + f = open(filename, "r") except IOError: return kv for line in f: try: - k, v = line.split(':', 1) + k, v = line.split(":", 1) except ValueError as e: - warning(_("Invalid line in RC file ({file}):" - " '{line}' ({error})\n").format( - line=line, error=e, file=filename)) + warning( + _("Invalid line in RC file ({file}):" " '{line}' ({error})\n").format( + line=line, error=e, file=filename + ) + ) continue kv[k.strip()] = v.strip() if not kv: @@ -548,9 +588,9 @@ def read_gisrc(filename): def read_env_file(path): kv = {} - f = open(path, 'r') + f = open(path, "r") for line in f: - k, v = line.split(':', 1) + k, v = line.split(":", 1) kv[k.strip()] = v.strip() f.close() return kv @@ -559,7 +599,7 @@ def read_env_file(path): def write_gisrc(kv, filename, append=False): # use append=True to avoid a race condition between write_gisrc() and # grass_prompt() on startup (PR #548) - f = open(filename, 'a' if append else 'w') + f = open(filename, "a" if append else "w") for k, v in kv.items(): f.write("%s: %s\n" % (k, v)) f.close() @@ -570,9 +610,9 @@ def set_mapset_to_gisrc(gisrc, grassdb, location, mapset): kv = read_gisrc(gisrc) else: kv = {} - kv['GISDBASE'] = grassdb - kv['LOCATION_NAME'] = location - kv['MAPSET'] = mapset + kv["GISDBASE"] = grassdb + kv["LOCATION_NAME"] = location + kv["MAPSET"] = mapset write_gisrc(kv, gisrc) @@ -584,13 +624,13 @@ def read_gui(gisrc, default_gui): # Check for a reference to the GRASS user interface in the grassrc file if os.access(gisrc, os.R_OK): kv = read_gisrc(gisrc) - if 'GRASS_GUI' in os.environ: - grass_gui = os.environ['GRASS_GUI'] - elif 'GUI' in kv: - grass_gui = kv['GUI'] - elif 'GRASS_GUI' in kv: + if "GRASS_GUI" in os.environ: + grass_gui = os.environ["GRASS_GUI"] + elif "GUI" in kv: + grass_gui = kv["GUI"] + elif "GRASS_GUI" in kv: # For backward compatibility (GRASS_GUI renamed to GUI) - grass_gui = kv['GRASS_GUI'] + grass_gui = kv["GRASS_GUI"] else: # Set the GRASS user interface to the default if needed grass_gui = default_gui @@ -598,11 +638,11 @@ def read_gui(gisrc, default_gui): if not grass_gui: grass_gui = default_gui - if grass_gui == 'gui': + if grass_gui == "gui": grass_gui = default_gui # FIXME oldtcltk, gis.m, d.m no longer exist (remove this around 7.2) - if grass_gui in ['d.m', 'gis.m', 'oldtcltk', 'tcltk']: + if grass_gui in ["d.m", "gis.m", "oldtcltk", "tcltk"]: warning(_("GUI <%s> not supported in this version") % grass_gui) grass_gui = default_gui @@ -629,46 +669,46 @@ def path_append(directory, var): def set_paths(grass_config_dir): # addons (path) - addon_path = os.getenv('GRASS_ADDON_PATH') + addon_path = os.getenv("GRASS_ADDON_PATH") if addon_path: for path in addon_path.split(os.pathsep): - path_prepend(addon_path, 'PATH') + path_prepend(addon_path, "PATH") # addons (base) - addon_base = os.getenv('GRASS_ADDON_BASE') + addon_base = os.getenv("GRASS_ADDON_BASE") if not addon_base: - addon_base = os.path.join(grass_config_dir, 'addons') - os.environ['GRASS_ADDON_BASE'] = addon_base + addon_base = os.path.join(grass_config_dir, "addons") + os.environ["GRASS_ADDON_BASE"] = addon_base if not WINDOWS: - path_prepend(os.path.join(addon_base, 'scripts'), 'PATH') - path_prepend(os.path.join(addon_base, 'bin'), 'PATH') + path_prepend(os.path.join(addon_base, "scripts"), "PATH") + path_prepend(os.path.join(addon_base, "bin"), "PATH") # standard installation if not WINDOWS: - path_prepend(gpath('scripts'), 'PATH') - path_prepend(gpath('bin'), 'PATH') + path_prepend(gpath("scripts"), "PATH") + path_prepend(gpath("bin"), "PATH") # Set PYTHONPATH to find GRASS Python modules - if os.path.exists(gpath('etc', 'python')): - pythonpath = gpath('etc', 'python') - path_prepend(pythonpath, 'PYTHONPATH') + if os.path.exists(gpath("etc", "python")): + pythonpath = gpath("etc", "python") + path_prepend(pythonpath, "PYTHONPATH") # the env var PYTHONPATH is only evaluated when python is started, # thus: sys.path.append(pythonpath) # now we can import stuff from GRASS lib/python # set path for the GRASS man pages - grass_man_path = gpath('docs', 'man') - addons_man_path = os.path.join(addon_base, 'docs', 'man') - man_path = os.getenv('MANPATH') + grass_man_path = gpath("docs", "man") + addons_man_path = os.path.join(addon_base, "docs", "man") + man_path = os.getenv("MANPATH") sys_man_path = None if man_path: - path_prepend(addons_man_path, 'MANPATH') - path_prepend(grass_man_path, 'MANPATH') + path_prepend(addons_man_path, "MANPATH") + path_prepend(grass_man_path, "MANPATH") else: try: - nul = open(os.devnull, 'w') - p = Popen(['manpath'], stdout=subprocess.PIPE, stderr=nul) + nul = open(os.devnull, "w") + p = Popen(["manpath"], stdout=subprocess.PIPE, stderr=nul) nul.close() s = p.stdout.read() p.wait() @@ -677,12 +717,12 @@ def set_paths(grass_config_dir): pass if sys_man_path: - os.environ['MANPATH'] = to_text_string(sys_man_path) - path_prepend(addons_man_path, 'MANPATH') - path_prepend(grass_man_path, 'MANPATH') + os.environ["MANPATH"] = to_text_string(sys_man_path) + path_prepend(addons_man_path, "MANPATH") + path_prepend(grass_man_path, "MANPATH") else: - os.environ['MANPATH'] = to_text_string(addons_man_path) - path_prepend(grass_man_path, 'MANPATH') + os.environ["MANPATH"] = to_text_string(addons_man_path) + path_prepend(grass_man_path, "MANPATH") # Set LD_LIBRARY_PATH (etc) to find GRASS shared libraries # this works for subprocesses but won't affect the current process @@ -690,7 +730,7 @@ def set_paths(grass_config_dir): def find_exe(pgm): - for directory in os.getenv('PATH').split(os.pathsep): + for directory in os.getenv("PATH").split(os.pathsep): path = os.path.join(directory, pgm) if os.access(path, os.X_OK): return path @@ -699,7 +739,7 @@ def find_exe(pgm): def set_defaults(): # GRASS_PAGER - if not os.getenv('GRASS_PAGER'): + if not os.getenv("GRASS_PAGER"): if find_exe("more"): pager = "more" elif find_exe("less"): @@ -708,41 +748,41 @@ def set_defaults(): pager = "more" else: pager = "cat" - os.environ['GRASS_PAGER'] = pager + os.environ["GRASS_PAGER"] = pager # GRASS_PYTHON - if not os.getenv('GRASS_PYTHON'): + if not os.getenv("GRASS_PYTHON"): if WINDOWS: - os.environ['GRASS_PYTHON'] = "python3.exe" + os.environ["GRASS_PYTHON"] = "python3.exe" else: - os.environ['GRASS_PYTHON'] = "python3" + os.environ["GRASS_PYTHON"] = "python3" # GRASS_GNUPLOT - if not os.getenv('GRASS_GNUPLOT'): - os.environ['GRASS_GNUPLOT'] = "gnuplot -persist" + if not os.getenv("GRASS_GNUPLOT"): + os.environ["GRASS_GNUPLOT"] = "gnuplot -persist" # GRASS_PROJSHARE - if not os.getenv('GRASS_PROJSHARE'): - os.environ['GRASS_PROJSHARE'] = CONFIG_PROJSHARE + if not os.getenv("GRASS_PROJSHARE"): + os.environ["GRASS_PROJSHARE"] = CONFIG_PROJSHARE def set_display_defaults(): """ Predefine monitor size for certain architectures""" - if os.getenv('HOSTTYPE') == 'arm': + if os.getenv("HOSTTYPE") == "arm": # small monitor on ARM (iPAQ, zaurus... etc) - os.environ['GRASS_RENDER_HEIGHT'] = "320" - os.environ['GRASS_RENDER_WIDTH'] = "240" + os.environ["GRASS_RENDER_HEIGHT"] = "320" + os.environ["GRASS_RENDER_WIDTH"] = "240" def set_browser(): # GRASS_HTML_BROWSER - browser = os.getenv('GRASS_HTML_BROWSER') + browser = os.getenv("GRASS_HTML_BROWSER") if not browser: 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" + browser = gpath("etc", "html_browser_mac.sh") + os.environ["GRASS_HTML_BROWSER_MACOSX"] = "-b com.apple.helpviewer" if WINDOWS: browser = "start" @@ -750,9 +790,24 @@ def set_browser(): browser = "explorer" else: # the usual suspects - browsers = ["xdg-open", "x-www-browser", "htmlview", "konqueror", "mozilla", - "mozilla-firefox", "firefox", "iceweasel", "opera", "google-chrome", - "chromium", "netscape", "dillo", "lynx", "links", "w3c"] + browsers = [ + "xdg-open", + "x-www-browser", + "htmlview", + "konqueror", + "mozilla", + "mozilla-firefox", + "firefox", + "iceweasel", + "opera", + "google-chrome", + "chromium", + "netscape", + "dillo", + "lynx", + "links", + "w3c", + ] for b in browsers: if find_exe(b): browser = b @@ -761,41 +816,47 @@ def set_browser(): elif MACOSX: # OSX doesn't execute browsers from the shell PATH - route through a # script - os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b %s" % browser - browser = gpath('etc', "html_browser_mac.sh") + os.environ["GRASS_HTML_BROWSER_MACOSX"] = "-b %s" % browser + browser = gpath("etc", "html_browser_mac.sh") if not browser: # even so we set to 'xdg-open' as a generic fallback browser = "xdg-open" - os.environ['GRASS_HTML_BROWSER'] = browser + os.environ["GRASS_HTML_BROWSER"] = browser def ensure_home(): """Set HOME if not set on MS Windows""" - if WINDOWS and not os.getenv('HOME'): - os.environ['HOME'] = os.path.join(os.getenv('HOMEDRIVE'), - os.getenv('HOMEPATH')) + if WINDOWS and not os.getenv("HOME"): + os.environ["HOME"] = os.path.join(os.getenv("HOMEDRIVE"), os.getenv("HOMEPATH")) def create_initial_gisrc(filename): # for convenience, define GISDBASE as pwd: - s = r"""GISDBASE: %s + s = ( + r"""GISDBASE: %s LOCATION_NAME: MAPSET: -""" % os.getcwd() +""" + % os.getcwd() + ) writefile(filename, s) 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') - p = Popen([os.environ['GRASS_PYTHON']], stdin=subprocess.PIPE, - stdout=nul, stderr=nul) + if expected_gui in ("wxpython", "gtext"): + nul = open(os.devnull, "w") + p = Popen( + [os.environ["GRASS_PYTHON"]], + stdin=subprocess.PIPE, + stdout=nul, + stderr=nul, + ) nul.close() p.stdin.write("variable=True".encode(ENCODING)) p.stdin.close() @@ -803,24 +864,30 @@ def check_gui(expected_gui): msg = None if p.returncode != 0: # Python was not found - switch to text interface mode - msg = _("The python command does not work as expected.\n" - "Please check your installation or set the GRASS_PYTHON" - " environment variable.") + msg = _( + "The python command does not work as expected.\n" + "Please check your installation or set the GRASS_PYTHON" + " environment variable." + ) if not os.path.exists(wxpath("wxgui.py")): msg = _("GRASS GUI not found. Please check your installation.") if msg: warning(_("{}\nSwitching to text based interface mode.").format(msg)) - grass_gui = 'text' + grass_gui = "text" else: # Display a message if a graphical interface was expected - if expected_gui != 'text': + if expected_gui != "text": # Set the interface mode to text - warning(_("It appears that the X Windows system is not active.\n" - "A graphical based user interface is not supported.\n" - "(DISPLAY variable is not set.)\n" - "Switching to text based interface mode.")) - grass_gui = 'text' + warning( + _( + "It appears that the X Windows system is not active.\n" + "A graphical based user interface is not supported.\n" + "(DISPLAY variable is not set.)\n" + "Switching to text based interface mode." + ) + ) + grass_gui = "text" return grass_gui @@ -828,7 +895,7 @@ def save_gui(gisrc, grass_gui): """Save the user interface variable in the grassrc file""" if os.access(gisrc, os.F_OK): kv = read_gisrc(gisrc) - kv['GUI'] = grass_gui + kv["GUI"] = grass_gui write_gisrc(kv, gisrc) @@ -841,29 +908,29 @@ def create_location(gisdbase, location, geostring): :param location: name of new Location :param geostring: path to a georeferenced file or EPSG code """ - if gpath('etc', 'python') not in sys.path: - sys.path.append(gpath('etc', 'python')) + if gpath("etc", "python") not in sys.path: + sys.path.append(gpath("etc", "python")) from grass.script import core as gcore # pylint: disable=E0611 try: - if geostring and geostring.upper().find('EPSG:') > -1: + if geostring and geostring.upper().find("EPSG:") > -1: # create location using EPSG code - epsg = geostring.split(':', 1)[1] - if ':' in epsg: - epsg, datum_trans = epsg.split(':', 1) + epsg = geostring.split(":", 1)[1] + if ":" in epsg: + epsg, datum_trans = epsg.split(":", 1) else: datum_trans = None - gcore.create_location(gisdbase, location, - epsg=epsg, datum_trans=datum_trans) - elif geostring == 'XY': + gcore.create_location( + gisdbase, location, epsg=epsg, datum_trans=datum_trans + ) + elif geostring == "XY": # create an XY location gcore.create_location(gisdbase, location) else: # create location using georeferenced file - gcore.create_location(gisdbase, location, - filename=geostring) + gcore.create_location(gisdbase, location, filename=geostring) except gcore.ScriptError as err: - fatal(err.value.strip('"').strip("'").replace('\\n', os.linesep)) + fatal(err.value.strip('"').strip("'").replace("\\n", os.linesep)) def can_create_location(gisdbase, location): @@ -888,24 +955,38 @@ def cannot_create_location_reason(gisdbase, location): path = os.path.join(gisdbase, location) if is_location_valid(gisdbase, location): - return _("Unable to create new location because" - " the location <{location}>" - " already exists.").format(**locals()) + return _( + "Unable to create new location because" + " the location <{location}>" + " already exists." + ).format(**locals()) elif os.path.isfile(path): - return _("Unable to create new location <{location}> because" - " <{path}> is a file.").format(**locals()) + return _( + "Unable to create new location <{location}> because" " <{path}> is a file." + ).format(**locals()) elif os.path.isdir(path): - return _("Unable to create new location <{location}> because" - " the directory <{path}>" - " already exists.").format(**locals()) + return _( + "Unable to create new location <{location}> because" + " the directory <{path}>" + " already exists." + ).format(**locals()) else: - return _("Unable to create new location in" - " the directory <{path}>" - " for an unknown reason.").format(**locals()) - - -def set_mapset(gisrc, arg=None, geofile=None, create_new=False, - tmp_location=False, tmp_mapset=False, tmpdir=None): + return _( + "Unable to create new location in" + " the directory <{path}>" + " for an unknown reason." + ).format(**locals()) + + +def set_mapset( + gisrc, + arg=None, + geofile=None, + create_new=False, + tmp_location=False, + tmp_mapset=False, + tmpdir=None, +): """Selected Location and Mapset are checked and created if requested The gisrc (GRASS environment file) is written at the end @@ -921,6 +1002,7 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False, get_location_invalid_suggestion, mapset_exists, ) + # TODO: arg param seems to be always the mapset parameter (or a dash # in a distant past), refactor l = arg @@ -930,7 +1012,7 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False, # so that trailing / is stripped away and split then always returns # non-empty element as the last element (which is good for both mapset # and location split) - if l == '.': + if l == ".": l = os.getcwd() elif not os.path.isabs(l): l = os.path.abspath(l) @@ -957,8 +1039,11 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False, location_name = "tmploc" # we need only one mapset mapset = "PERMANENT" - debug("Using temporary location <{gdb}{sep}{lc}>".format( - gdb=gisdbase, lc=location_name, sep=os.path.sep)) + debug( + "Using temporary location <{gdb}{sep}{lc}>".format( + gdb=gisdbase, lc=location_name, sep=os.path.sep + ) + ) if gisdbase and location_name and mapset: path = os.path.join(gisdbase, location_name, mapset) @@ -970,9 +1055,12 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False, # generating the name, we could just try another name in case of # conflict. Conflict is unlikely, but it would be worth considering # it during refactoring of this code. - fatal(_("Mapset <{}> already exists." - " Unable to create a new temporary mapset of that name.") - .format(path)) + fatal( + _( + "Mapset <{}> already exists." + " Unable to create a new temporary mapset of that name." + ).format(path) + ) elif path_is_valid_mapset and create_new: fatal(_("Mapset <{}> already exists.").format(path)) @@ -1002,21 +1090,23 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False, mapset = "PERMANENT" if tmp_mapset: suggestion = get_location_invalid_suggestion( - gisdbase, location_name) - reason = get_location_invalid_reason( - gisdbase, location_name) + gisdbase, location_name + ) + reason = get_location_invalid_reason(gisdbase, location_name) if suggestion: fatal("{reason}\n{suggestion}".format(**locals())) else: fatal(reason) if not can_create_location(gisdbase, location_name): - fatal(cannot_create_location_reason( - gisdbase, location_name)) + fatal(cannot_create_location_reason(gisdbase, location_name)) # create new location based on the provided EPSG/... if not geofile: fatal(_("Provide CRS to create a location")) - message(_("Creating new GRASS GIS location <{}>...") - .format(location_name)) + message( + _("Creating new GRASS GIS location <{}>...").format( + location_name + ) + ) create_location(gisdbase, location_name, geofile) else: # 'location_name' is a valid GRASS location, @@ -1024,23 +1114,34 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False, if os.path.isfile(path): # not a valid mapset, but dir exists, assuming # broken/incomplete mapset - fatal(_("Unable to create new mapset <{mapset}>" - " because <{path}> is a file.") - .format(mapset=mapset, path=path)) + fatal( + _( + "Unable to create new mapset <{mapset}>" + " because <{path}> is a file." + ).format(mapset=mapset, path=path) + ) elif os.path.isdir(path): # not a valid mapset, but dir exists, assuming # broken/incomplete mapset - warning(_("The mapset <{}> is missing the WIND file" - " (computational region). It will be" - " fixed now. Note that this warning" - " may become an error in future versions.") - .format(mapset)) + warning( + _( + "The mapset <{}> is missing the WIND file" + " (computational region). It will be" + " fixed now. Note that this warning" + " may become an error in future versions." + ).format(mapset) + ) else: if geofile: - fatal(_("No CRS is needed for creating mapset." - " Did you mean to create a new location?")) - message(_("Creating new GRASS GIS mapset <{}>...") - .format(mapset)) + fatal( + _( + "No CRS is needed for creating mapset." + " Did you mean to create a new location?" + ) + ) + message( + _("Creating new GRASS GIS mapset <{}>...").format(mapset) + ) # create mapset directory os.mkdir(path) if tmp_mapset: @@ -1058,14 +1159,21 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False, ) # make directory a mapset, add the region # copy PERMANENT/DEFAULT_WIND to /WIND - s = readfile(os.path.join(gisdbase, location_name, - "PERMANENT", "DEFAULT_WIND")) + s = readfile( + os.path.join( + gisdbase, location_name, "PERMANENT", "DEFAULT_WIND" + ) + ) writefile(os.path.join(path, "WIND"), s) set_mapset_to_gisrc(gisrc, gisdbase, location_name, mapset) else: - fatal(_("GRASS GIS database directory, location and mapset" + fatal( + _( + "GRASS GIS database directory, location and mapset" " not set properly." - " Use GUI or command line to set them.")) + " Use GUI or command line to set them." + ) + ) def set_mapset_interactive(grass_gui): @@ -1073,31 +1181,36 @@ def set_mapset_interactive(grass_gui): The gisrc (GRASS environment file) is written at the end. """ - if not os.path.exists(wxpath("gis_set.py")) and grass_gui != 'text': + if not os.path.exists(wxpath("gis_set.py")) and grass_gui != "text": debug("No GUI available, switching to text mode") return False # Check for text interface - if grass_gui == 'text': + if grass_gui == "text": # TODO: maybe this should be removed and solved from outside # this depends on what we expect from this function # should gisrc be ok after running or is it allowed to be still not set pass # Check for GUI - elif grass_gui in ('gtext', 'wxpython'): + elif grass_gui in ("gtext", "wxpython"): gui_startup(grass_gui) else: # Shouldn't need this but you never know - fatal(_("Invalid user interface specified - <%s>. " - "Use the --help option to see valid interface names.") % grass_gui) + fatal( + _( + "Invalid user interface specified - <%s>. " + "Use the --help option to see valid interface names." + ) + % grass_gui + ) return True def gui_startup(grass_gui): """Start GUI for startup (setting gisrc file)""" - if grass_gui in ('wxpython', 'gtext'): - ret = call([os.getenv('GRASS_PYTHON'), wxpath("gis_set.py")]) + if grass_gui in ("wxpython", "gtext"): + ret = call([os.getenv("GRASS_PYTHON"), wxpath("gis_set.py")]) # this if could be simplified to three branches (0, 5, rest) # if there is no need to handle unknown code separately @@ -1108,7 +1221,9 @@ def gui_startup(grass_gui): # 2 probably file not found from python interpreter # formerly we were starting in text mode instead, now we just fail # which is more straightforward for everybody - fatal(_("Error in GUI startup. See messages above (if any)" + fatal( + _( + "Error in GUI startup. See messages above (if any)" " and if necessary, please" " report this error to the GRASS developers.\n" "On systems with package manager, make sure you have the right" @@ -1116,15 +1231,20 @@ def gui_startup(grass_gui): "To run GRASS GIS in text mode use the --text flag.\n" "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)) + "See also: https://grass.osgeo.org/{cmd_name}/manuals/helptext.html" + ).format(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.")) sys.exit(0) else: - fatal(_("Invalid return code from GUI startup script.\n" - "Please advise GRASS developers of this error.")) + fatal( + _( + "Invalid return code from GUI startup script.\n" + "Please advise GRASS developers of this error." + ) + ) # we don't follow the LOCATION_NAME legacy naming here but we have to still @@ -1148,8 +1268,7 @@ def __init__(self): @property def full_mapset(self): if self._full_mapset is None: - self._full_mapset = os.path.join(self.gisdbase, self.location, - self.mapset) + self._full_mapset = os.path.join(self.gisdbase, self.location, self.mapset) return self._full_mapset # TODO: perhaps conversion to bool would be nicer @@ -1167,19 +1286,24 @@ def load_gisrc(gisrc, gisrcrc): """ mapset_settings = MapsetSettings() kv = read_gisrc(gisrc) - mapset_settings.gisdbase = kv.get('GISDBASE') - mapset_settings.location = kv.get('LOCATION_NAME') - mapset_settings.mapset = kv.get('MAPSET') + mapset_settings.gisdbase = kv.get("GISDBASE") + mapset_settings.location = kv.get("LOCATION_NAME") + mapset_settings.mapset = kv.get("MAPSET") if not mapset_settings.is_valid(): - fatal(_("Error reading data path information from g.gisenv.\n" + fatal( + _( + "Error reading data path information from g.gisenv.\n" "GISDBASE={gisdbase}\n" "LOCATION_NAME={location}\n" "MAPSET={mapset}\n\n" - "Check the <{file}> file.").format( - gisdbase=mapset_settings.gisdbase, - location=mapset_settings.location, - mapset=mapset_settings.mapset, - file=gisrcrc)) + "Check the <{file}> file." + ).format( + gisdbase=mapset_settings.gisdbase, + location=mapset_settings.location, + mapset=mapset_settings.mapset, + file=gisrcrc, + ) + ) return mapset_settings @@ -1189,9 +1313,9 @@ def can_start_in_gisrc_mapset(gisrc, ignore_lock=False): mapset_settings = MapsetSettings() kv = read_gisrc(gisrc) - mapset_settings.gisdbase = kv.get('GISDBASE') - mapset_settings.location = kv.get('LOCATION_NAME') - mapset_settings.mapset = kv.get('MAPSET') + mapset_settings.gisdbase = kv.get("GISDBASE") + mapset_settings.location = kv.get("LOCATION_NAME") + mapset_settings.mapset = kv.get("MAPSET") if not mapset_settings.is_valid(): return False return can_start_in_mapset( @@ -1207,7 +1331,7 @@ def load_env(grass_env_file): # Regular expression for lines starting with "export var=val" (^export # lines below). Environment variables should start with a-zA-Z or _. # \1 and \2 are a variable name and its value, respectively. - export_re = re.compile('^export[ \t]+([a-zA-Z_]+[a-zA-Z0-9_]*)=(.*?)[ \t]*$') + export_re = re.compile("^export[ \t]+([a-zA-Z_]+[a-zA-Z0-9_]*)=(.*?)[ \t]*$") for line in readfile(grass_env_file).split(os.linesep): # match ^export lines @@ -1237,29 +1361,35 @@ def load_env(grass_env_file): v = v.strip('"') # we'll keep expand=True to expand $var's inside "value" because # they are within double quotes - elif v.startswith("'") or v.endswith("'") or v.startswith('"') or v.endswith('"'): + elif ( + v.startswith("'") or v.endswith("'") or v.startswith('"') or v.endswith('"') + ): # here, let's try to ignore unmatching single/double quotes, which # might be a multi-line variable or just a user error debug("Ignoring multi-line environmental variable {0}".format(k)) continue if expand: # finally, expand $var's within a non-single quoted value - v = os.path.expanduser(os.path.expandvars(v.replace('\\$', '\0')).replace('\0', '$')) + v = os.path.expanduser( + os.path.expandvars(v.replace("\\$", "\0")).replace("\0", "$") + ) debug("Environmental variable set {0}={1}".format(k, v)) # create a new environment variable os.environ[k] = v # Allow for mixed ISIS-GRASS Environment - if os.getenv('ISISROOT'): - isis = os.getenv('ISISROOT') - os.environ['ISIS_LIB'] = isis + os.sep + "lib" - os.environ['ISIS_3RDPARTY'] = isis + os.sep + "3rdParty" + os.sep + "lib" - os.environ['QT_PLUGIN_PATH'] = isis + os.sep + "3rdParty" + os.sep + "plugins" + if os.getenv("ISISROOT"): + isis = os.getenv("ISISROOT") + os.environ["ISIS_LIB"] = isis + os.sep + "lib" + os.environ["ISIS_3RDPARTY"] = isis + os.sep + "3rdParty" + os.sep + "lib" + os.environ["QT_PLUGIN_PATH"] = isis + os.sep + "3rdParty" + os.sep + "plugins" # os.environ['ISIS3DATA'] = isis + "$ISIS3DATA" - libpath = os.getenv('LD_LIBRARY_PATH', '') - isislibpath = os.getenv('ISIS_LIB') - isis3rdparty = os.getenv('ISIS_3RDPARTY') - os.environ['LD_LIBRARY_PATH'] = libpath + os.pathsep + isislibpath + os.pathsep + isis3rdparty + libpath = os.getenv("LD_LIBRARY_PATH", "") + isislibpath = os.getenv("ISIS_LIB") + isis3rdparty = os.getenv("ISIS_3RDPARTY") + os.environ["LD_LIBRARY_PATH"] = ( + libpath + os.pathsep + isislibpath + os.pathsep + isis3rdparty + ) def install_notranslation(): @@ -1267,7 +1397,8 @@ def install_notranslation(): # This function just installs _ as a pass-through function # See trac #3875 for details import builtins - builtins.__dict__['_'] = lambda x: x + + builtins.__dict__["_"] = lambda x: x def set_language(grass_config_dir): @@ -1279,56 +1410,63 @@ def set_language(grass_config_dir): # thus it always on Vista and XP will print an error. # See discussion for Windows not following its own documentation and # not accepting ISO codes as valid locale identifiers http://bugs.python.org/issue10466 - language = 'None' # Such string sometimes is present in wx file + language = "None" # Such string sometimes is present in wx file encoding = None # Override value is stored in wxGUI preferences file. # As it's the only thing required, we'll just grep it out. try: - fd = open(os.path.join(grass_config_dir, 'wx'), 'r') + fd = open(os.path.join(grass_config_dir, "wx"), "r") except: # Even if there is no override, we still need to set locale. pass else: for line in fd: - if re.search('^language', line): - line = line.rstrip(' %s' % os.linesep) - language = ''.join(line.split(';')[-1:]) + if re.search("^language", line): + line = line.rstrip(" %s" % os.linesep) + language = "".join(line.split(";")[-1:]) break fd.close() # Backwards compatibility with old wx preferences files - if language == 'C': - language = 'en' + if language == "C": + language = "en" - if language == 'None' or language == '' or not language: + if language == "None" or language == "" or not language: # Language override is disabled (system language specified) # As by default program runs with C locale, but users expect to # have their default locale, we'll just set default locale try: - locale.setlocale(locale.LC_ALL, '') + locale.setlocale(locale.LC_ALL, "") except locale.Error as e: # If we get here, system locale settings are terribly wrong # There is no point to continue as GRASS/Python will fail # in some other unpredictable way. sys.stderr.write( "System locale is not usable (LC_ALL variable not defined)." - " Most likely it indicates misconfigured environment.\n") + " Most likely it indicates misconfigured environment.\n" + ) sys.stderr.write("Reported error message: %s\n" % e) # it would be too drastic to exit # sys.exit("Fix system locale settings and then try again.") - locale.setlocale(locale.LC_ALL, 'C') - sys.stderr.write("Default locale settings are missing. GRASS running with C locale.\n") + locale.setlocale(locale.LC_ALL, "C") + sys.stderr.write( + "Default locale settings are missing. GRASS running with C locale.\n" + ) language, encoding = locale.getdefaultlocale() if not language: - sys.stderr.write("Default locale settings are missing. GRASS running with C locale.\n") + sys.stderr.write( + "Default locale settings are missing. GRASS running with C locale.\n" + ) install_notranslation() return else: - debug("A language override has been requested." - " Trying to switch GRASS into '%s'..." % language) + debug( + "A language override has been requested." + " Trying to switch GRASS into '%s'..." % language + ) try: locale.setlocale(locale.LC_ALL, language) except locale.Error as e: @@ -1337,25 +1475,26 @@ def set_language(grass_config_dir): # UTF-8 encoding before giving up as on Linux systems # lang.UTF-8 locales are more common than legacy # ISO-8859 ones. - encoding = 'UTF-8' - normalized = locale.normalize('%s.%s' % (language, encoding)) + encoding = "UTF-8" + normalized = locale.normalize("%s.%s" % (language, encoding)) locale.setlocale(locale.LC_ALL, normalized) except locale.Error as e: - if language == 'en': + if language == "en": # A workaround for Python Issue30755 # https://bugs.python.org/issue30755 - if locale.normalize('C.UTF-8') == 'en_US.UTF-8': - locale.setlocale(locale.LC_ALL, 'C') - os.environ['LANGUAGE'] = 'C' - os.environ['LANG'] = 'C' - os.environ['LC_MESSAGES'] = 'C' - os.environ['LC_NUMERIC'] = 'C' - os.environ['LC_TIME'] = 'C' + if locale.normalize("C.UTF-8") == "en_US.UTF-8": + locale.setlocale(locale.LC_ALL, "C") + os.environ["LANGUAGE"] = "C" + os.environ["LANG"] = "C" + os.environ["LC_MESSAGES"] = "C" + os.environ["LC_NUMERIC"] = "C" + os.environ["LC_TIME"] = "C" sys.stderr.write( "To avoid Unicode errors in GUI, install" " en_US.UTF-8 locale and restart GRASS.\n" "Also consider upgrading your Python version" - " to one containing fix for Python Issue 30755.\n") + " to one containing fix for Python Issue 30755.\n" + ) install_notranslation() return # en_US locale might be missing, still all messages in @@ -1364,57 +1503,63 @@ def set_language(grass_config_dir): # thus lets try our luck with C.UTF-8 first. # See bugs #3441 and #3423 try: - locale.setlocale(locale.LC_ALL, 'C.UTF-8') + locale.setlocale(locale.LC_ALL, "C.UTF-8") except locale.Error as e: # All lost. Setting to C as much as possible. # We can not call locale.normalize on C as it # will transform it to en_US and we already know # it doesn't work. - locale.setlocale(locale.LC_ALL, 'C') - os.environ['LANGUAGE'] = 'C' - os.environ['LANG'] = 'C' - os.environ['LC_MESSAGES'] = 'C' - os.environ['LC_NUMERIC'] = 'C' - os.environ['LC_TIME'] = 'C' - gettext.install('grasslibs', gpath('locale')) + locale.setlocale(locale.LC_ALL, "C") + os.environ["LANGUAGE"] = "C" + os.environ["LANG"] = "C" + os.environ["LC_MESSAGES"] = "C" + os.environ["LC_NUMERIC"] = "C" + os.environ["LC_TIME"] = "C" + gettext.install("grasslibs", gpath("locale")) sys.stderr.write( "All attempts to enable English language have" " failed. GRASS running with C locale.\n" "If you observe UnicodeError in Python," " install en_US.UTF-8" - " locale and restart GRASS.\n") + " locale and restart GRASS.\n" + ) install_notranslation() return else: # The last attempt... try: encoding = locale.getpreferredencoding() - normalized = locale.normalize('%s.%s' % (language, encoding)) + normalized = locale.normalize("%s.%s" % (language, encoding)) locale.setlocale(locale.LC_ALL, normalized) except locale.Error as e: # If we got so far, attempts to set up language and locale have failed # on this system - sys.stderr.write("Failed to enforce user specified language '%s' with error: '%s'\n" % (language, e)) - sys.stderr.write("A LANGUAGE environmental variable has been set.\nPart of messages will be displayed in the requested language.\n") + sys.stderr.write( + "Failed to enforce user specified language '%s' with error: '%s'\n" + % (language, e) + ) + sys.stderr.write( + "A LANGUAGE environmental variable has been set.\nPart of messages will be displayed in the requested language.\n" + ) # Even if setting locale will fail, let's set LANG in a hope, # that UI will use it GRASS texts will be in selected language, # system messages (i.e. OK, Cancel etc.) - in system default # language - os.environ['LANGUAGE'] = language - os.environ['LANG'] = language + os.environ["LANGUAGE"] = language + os.environ["LANG"] = language install_notranslation() return # Set up environment for subprocesses - os.environ['LANGUAGE'] = language - os.environ['LANG'] = language + os.environ["LANGUAGE"] = language + os.environ["LANG"] = language - if WINDOWS and (language == 'ko' or (language == 'ko_KR' and encoding == 'cp949')): + if WINDOWS and (language == "ko" or (language == "ko_KR" and encoding == "cp949")): # The default encoding for the Korean language in Windows is cp949, # Microsoft's proprietary extension to euc-kr, but gettext prints no # translated messages at all in the Command Prompt window if LC_CTYPE # is set to ko_KR.cp949. Here, force LC_CTYPE to be euc-kr. - normalized = 'euc-kr' + normalized = "euc-kr" encoding = None # XXX: In UN*X, LC_CTYPE needs to be set to *any* value before GRASS @@ -1422,27 +1567,37 @@ def set_language(grass_config_dir): # example, 'LC_CTYPE= grass' will break the welcome message. # Interestingly, modules' help messages look fine. elif encoding: - normalized = locale.normalize('%s.%s' % (language, encoding)) + normalized = locale.normalize("%s.%s" % (language, encoding)) else: normalized = language - for lc in ('LC_CTYPE', 'LC_MESSAGES', 'LC_TIME', 'LC_COLLATE', - 'LC_MONETARY', 'LC_PAPER', 'LC_NAME', 'LC_ADDRESS', - 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION'): + for lc in ( + "LC_CTYPE", + "LC_MESSAGES", + "LC_TIME", + "LC_COLLATE", + "LC_MONETARY", + "LC_PAPER", + "LC_NAME", + "LC_ADDRESS", + "LC_TELEPHONE", + "LC_MEASUREMENT", + "LC_IDENTIFICATION", + ): os.environ[lc] = normalized # Some code in GRASS might not like other decimal separators than . # Other potential sources for problems are: LC_TIME LC_CTYPE - locale.setlocale(locale.LC_NUMERIC, 'C') - os.environ['LC_NUMERIC'] = 'C' - if os.getenv('LC_ALL'): - del os.environ['LC_ALL'] # Remove LC_ALL to not override LC_NUMERIC + locale.setlocale(locale.LC_NUMERIC, "C") + os.environ["LC_NUMERIC"] = "C" + if os.getenv("LC_ALL"): + del os.environ["LC_ALL"] # Remove LC_ALL to not override LC_NUMERIC # From now on enforce the new language if encoding: - gettext.install('grasslibs', gpath('locale'), codeset=encoding) + gettext.install("grasslibs", gpath("locale"), codeset=encoding) else: - gettext.install('grasslibs', gpath('locale')) + gettext.install("grasslibs", gpath("locale")) # TODO: grass_gui parameter is a hack and should be removed, see below @@ -1460,7 +1615,10 @@ def lock_mapset(mapset_path, force_gislock_removal, user, grass_gui): mapset_uid = stat_info.st_uid if mapset_uid != os.getuid(): # GTC %s is mapset's folder path - error = "%s\n%s" % (error, _("You are not the owner of '%s'.") % mapset_path) + error = "%s\n%s" % ( + error, + _("You are not the owner of '%s'.") % mapset_path, + ) fatal(error) # Check for concurrent use lockfile = os.path.join(mapset_path, ".gislock") @@ -1468,33 +1626,43 @@ def lock_mapset(mapset_path, force_gislock_removal, user, grass_gui): msg = None if ret == 2: if not force_gislock_removal: - msg = _("%(user)s is currently running GRASS in selected mapset" - " (file %(file)s found). Concurrent use not allowed.\n" - "You can force launching GRASS using -f flag" - " (note that you need permission for this operation)." - " Have another look in the processor " - "manager just to be sure..." % { - 'user': user, 'file': lockfile}) + msg = _( + "%(user)s is currently running GRASS in selected mapset" + " (file %(file)s found). Concurrent use not allowed.\n" + "You can force launching GRASS using -f flag" + " (note that you need permission for this operation)." + " Have another look in the processor " + "manager just to be sure..." % {"user": user, "file": lockfile} + ) else: try_remove(lockfile) - message(_("%(user)s is currently running GRASS in selected mapset" - " (file %(file)s found). Forcing to launch GRASS..." % { - 'user': user, 'file': lockfile})) + message( + _( + "%(user)s is currently running GRASS in selected mapset" + " (file %(file)s found). Forcing to launch GRASS..." + % {"user": user, "file": lockfile} + ) + ) elif ret != 0: - msg = _("Unable to properly access '%s'.\n" - "Please notify system personnel.") % lockfile + msg = ( + _("Unable to properly access '%s'.\n" "Please notify system personnel.") + % lockfile + ) # TODO: the gui decision should be done by the caller # this needs some change to the function interface, return tuple or # use exceptions (better option) if msg: if grass_gui == "wxpython": - call([os.getenv('GRASS_PYTHON'), wxpath("gis_set_error.py"), msg]) + call([os.getenv("GRASS_PYTHON"), wxpath("gis_set_error.py"), msg]) # TODO: here we probably miss fatal or exit, needs to be added else: fatal(msg) - debug("Mapset <{mapset}> locked using '{lockfile}'".format( - mapset=mapset_path, lockfile=lockfile)) + debug( + "Mapset <{mapset}> locked using '{lockfile}'".format( + mapset=mapset_path, lockfile=lockfile + ) + ) return lockfile @@ -1511,7 +1679,7 @@ def unlock_gisrc_mapset(gisrc, gisrcrc): def make_fontcap(): # TODO: is GRASS_FONT_CAP ever defined? It seems it must be defined in system - fc = os.getenv('GRASS_FONT_CAP') + fc = os.getenv("GRASS_FONT_CAP") if fc and not os.access(fc, os.R_OK): message(_("Building user fontcap...")) call(["g.mkfontcap"]) @@ -1523,33 +1691,33 @@ def ensure_db_connected(mapset): :param mapset: full path to the mapset """ if not os.access(os.path.join(mapset, "VAR"), os.F_OK): - call(['db.connect', '-c', '--quiet']) + call(["db.connect", "-c", "--quiet"]) 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 os.getenv('GRASS_SH'): - os.environ['SHELL'] = os.getenv('GRASS_SH') - if not os.getenv('SHELL'): - os.environ['SHELL'] = os.getenv('COMSPEC', 'cmd.exe') + if os.getenv("GRASS_SH"): + os.environ["SHELL"] = os.getenv("GRASS_SH") + if not os.getenv("SHELL"): + os.environ["SHELL"] = os.getenv("COMSPEC", "cmd.exe") # cygwin has many problems with the shell setup # below, so i hardcoded everything here. - if sys.platform == 'cygwin': + if sys.platform == "cygwin": sh = "CYGWIN" shellname = "GNU Bash (Cygwin)" - os.environ['SHELL'] = "/usr/bin/bash.exe" - os.environ['OSTYPE'] = "cygwin" + os.environ["SHELL"] = "/usr/bin/bash.exe" + os.environ["OSTYPE"] = "cygwin" else: # in docker the 'SHELL' variable may not be # visible in a Python session unless 'ENV SHELL /bin/bash' is set in Dockerfile try: - sh = os.path.basename(os.getenv('SHELL')) + sh = os.path.basename(os.getenv("SHELL")) except: - sh = 'sh' - os.environ['SHELL'] = sh + sh = "sh" + os.environ["SHELL"] = sh if WINDOWS and sh: sh = os.path.splitext(sh)[0] @@ -1573,25 +1741,28 @@ def get_shell(): else: shellname = "shell" # check for SHELL - if not os.getenv('SHELL'): + if not os.getenv("SHELL"): fatal(_("The SHELL variable is not set")) return sh, shellname def get_grass_env_file(sh, grass_config_dir): """Get name of the shell-specific GRASS environment (rc) file""" - if sh in ['csh', 'tcsh']: - grass_env_file = os.path.join(grass_config_dir, 'cshrc') - elif sh in ['bash', 'msh', 'cygwin', 'sh']: - grass_env_file = os.path.join(grass_config_dir, 'bashrc') - elif sh == 'zsh': - grass_env_file = os.path.join(grass_config_dir, 'zshrc') - elif sh in ['cmd', 'powershell']: - grass_env_file = os.path.join(grass_config_dir, 'env.bat') + if sh in ["csh", "tcsh"]: + grass_env_file = os.path.join(grass_config_dir, "cshrc") + elif sh in ["bash", "msh", "cygwin", "sh"]: + grass_env_file = os.path.join(grass_config_dir, "bashrc") + elif sh == "zsh": + grass_env_file = os.path.join(grass_config_dir, "zshrc") + elif sh in ["cmd", "powershell"]: + grass_env_file = os.path.join(grass_config_dir, "env.bat") else: - grass_env_file = os.path.join(grass_config_dir, 'bashrc') - warning(_("Unsupported shell <{sh}>: {env_file}").format( - sh=sh, env_file=grass_env_file)) + grass_env_file = os.path.join(grass_config_dir, "bashrc") + warning( + _("Unsupported shell <{sh}>: {env_file}").format( + sh=sh, env_file=grass_env_file + ) + ) return grass_env_file @@ -1605,7 +1776,7 @@ def run_batch_job(batch_job): batch_job_string = batch_job if not isinstance(batch_job, six.string_types): # for messages only - batch_job_string = ' '.join(batch_job) + batch_job_string = " ".join(batch_job) message(_("Executing <%s> ...") % batch_job_string) def script_path(batch_job): @@ -1616,14 +1787,13 @@ def script_path(batch_job): :return str or None: script path or None """ script_in_addon_path = None - if 'GRASS_ADDON_BASE' in os.environ: + if "GRASS_ADDON_BASE" in os.environ: script_in_addon_path = os.path.join( - os.environ['GRASS_ADDON_BASE'], - 'scripts', + os.environ["GRASS_ADDON_BASE"], + "scripts", batch_job[0], ) - if script_in_addon_path and \ - os.path.exists(script_in_addon_path): + if script_in_addon_path and os.path.exists(script_in_addon_path): batch_job[0] = script_in_addon_path return script_in_addon_path elif os.path.exists(batch_job[0]): @@ -1633,11 +1803,10 @@ def script_path(batch_job): script = script_path(batch_job) proc = Popen(batch_job, shell=False, env=os.environ) except OSError as error: - error_message = _("Execution of <{cmd}> failed:\n" - "{error}").format( - cmd=batch_job_string, - error=error, - ) + error_message = _("Execution of <{cmd}> failed:\n" "{error}").format( + cmd=batch_job_string, + error=error, + ) # No such file or directory if error.errno == errno.ENOENT: if script and os.access(batch_job[0], os.X_OK): @@ -1664,19 +1833,20 @@ def start_gui(grass_gui): # Check for gui interface if grass_gui == "wxpython": # TODO: report failures - return Popen([os.getenv('GRASS_PYTHON'), wxpath("wxgui.py")]) + return Popen([os.getenv("GRASS_PYTHON"), wxpath("wxgui.py")]) return None def close_gui(): """Close GUI if running""" - if gpath('etc', 'python') not in sys.path: - sys.path.append(gpath('etc', 'python')) + if gpath("etc", "python") not in sys.path: + sys.path.append(gpath("etc", "python")) from grass.script import core as gcore # pylint: disable=E0611 + env = gcore.gisenv() - if 'GUI_PID' not in env: + if "GUI_PID" not in env: return - for pid in env['GUI_PID'].split(','): + for pid in env["GUI_PID"].split(","): debug("Exiting GUI with pid={0}".format(pid)) try: os.kill(int(pid), signal.SIGTERM) @@ -1686,27 +1856,29 @@ def close_gui(): def show_banner(): """Write GRASS GIS ASCII name to stderr""" - sys.stderr.write(r""" + sys.stderr.write( + r""" __________ ___ __________ _______________ / ____/ __ \/ | / ___/ ___/ / ____/ _/ ___/ / / __/ /_/ / /| | \__ \\_ \ / / __ / / \__ \ / /_/ / _, _/ ___ |___/ /__/ / / /_/ // / ___/ / \____/_/ |_/_/ |_/____/____/ \____/___//____/ -""") +""" + ) def say_hello(): """Write welcome to stderr including code revision if in git copy""" sys.stderr.write(_("Welcome to GRASS GIS %s") % GRASS_VERSION) - if GRASS_VERSION.endswith('dev'): + if GRASS_VERSION.endswith("dev"): try: - filerev = open(gpath('etc', 'VERSIONNUMBER')) - linerev = filerev.readline().rstrip('\n') + filerev = open(gpath("etc", "VERSIONNUMBER")) + linerev = filerev.readline().rstrip("\n") filerev.close() - revision = linerev.split(' ')[1] - sys.stderr.write(' (' + revision + ')') + revision = linerev.split(" ")[1] + sys.stderr.write(" (" + revision + ")") except: pass @@ -1722,16 +1894,21 @@ def say_hello(): def show_info(shellname, grass_gui, default_gui): """Write basic info about GRASS GIS and GRASS session to stderr""" - sys.stderr.write(f(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:"))) - - if grass_gui == 'wxpython': + sys.stderr.write( + f( + 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:"), + ) + ) + + if grass_gui == "wxpython": message(f("%-41sg.gui wxpython", _("If required, restart the GUI with:"))) else: message(f("%-41sg.gui %s", _("Start the GUI with:"), default_gui)) @@ -1741,32 +1918,31 @@ def show_info(shellname, grass_gui, default_gui): def csh_startup(location, grass_env_file): - userhome = os.getenv('HOME') # save original home + userhome = os.getenv("HOME") # save original home home = location - os.environ['HOME'] = home + os.environ["HOME"] = home cshrc = os.path.join(home, ".cshrc") tcshrc = os.path.join(home, ".tcshrc") try_remove(cshrc) try_remove(tcshrc) - f = open(cshrc, 'w') + f = open(cshrc, "w") f.write("set home = %s\n" % userhome) f.write("set history = 10000000 savehist = (10000000 merge) noclobber ignoreeof\n") - f.write("set histfile = %s\n" % os.path.join(os.getenv('HOME'), - ".history")) + f.write("set histfile = %s\n" % os.path.join(os.getenv("HOME"), ".history")) f.write("alias _location g.gisenv get=LOCATION_NAME\n") f.write("alias _mapset g.gisenv get=MAPSET\n") - f.write("alias precmd \'echo \"Mapset <`_mapset`> in Location <`_location`>\"\'\n") - f.write("set prompt=\"GRASS > \"\n") + f.write("alias precmd 'echo \"Mapset <`_mapset`> in Location <`_location`>\"'\n") + f.write('set prompt="GRASS > "\n') # csh shell rc file left for backward compatibility path = os.path.join(userhome, ".grass.cshrc") if os.access(path, os.R_OK): - f.write(readfile(path) + '\n') + f.write(readfile(path) + "\n") if os.access(grass_env_file, os.R_OK): - f.write(readfile(grass_env_file) + '\n') + f.write(readfile(grass_env_file) + "\n") mail_re = re.compile(r"^ *set *mail *= *") @@ -1779,81 +1955,84 @@ def csh_startup(location, grass_env_file): if mail_re.match(l): f.write(l) - path = os.getenv('PATH').split(':') - f.write("set path = ( %s ) \n" % ' '.join(path)) + path = os.getenv("PATH").split(":") + f.write("set path = ( %s ) \n" % " ".join(path)) f.close() writefile(tcshrc, readfile(cshrc)) - process = Popen([gpath("etc", "run"), os.getenv('SHELL')]) - os.environ['HOME'] = userhome + process = Popen([gpath("etc", "run"), os.getenv("SHELL")]) + os.environ["HOME"] = userhome return process def sh_like_startup(location, location_name, grass_env_file, sh): """Start Bash or Z shell (but not sh (Bourne Shell))""" - if sh == 'bash': + if sh == "bash": # set bash history to record an unlimited command history - sh_history_limit = "-1" # unlimited - os.environ['HISTSIZE'] = sh_history_limit - os.environ['HISTFILESIZE'] = sh_history_limit + sh_history_limit = "-1" # unlimited + os.environ["HISTSIZE"] = sh_history_limit + os.environ["HISTFILESIZE"] = sh_history_limit sh_history = ".bash_history" shrc = ".bashrc" grass_shrc = ".grass.bashrc" - elif sh == 'zsh': + elif sh == "zsh": # zsh does not have an unlimited history setting, so 1e8 is set as a proxy - sh_history_limit = "100000000" # proxy for unlimited - os.environ['SAVEHIST'] = sh_history_limit - os.environ['HISTSIZE'] = sh_history_limit + sh_history_limit = "100000000" # proxy for unlimited + os.environ["SAVEHIST"] = sh_history_limit + os.environ["HISTSIZE"] = sh_history_limit sh_history = ".zsh_history" shrc = ".zshrc" grass_shrc = ".grass.zshrc" else: raise ValueError( - 'Only bash-like and zsh shells are supported by sh_like_startup()') + "Only bash-like and zsh shells are supported by sh_like_startup()" + ) # save command history in mapset dir and remember more # bash histroy file handled in specific_addition if not sh == "bash": - os.environ['HISTFILE'] = os.path.join(location, sh_history) + os.environ["HISTFILE"] = os.path.join(location, sh_history) # instead of changing $HOME, start bash with: # --rcfile "$LOCATION/.bashrc" ? # if so, must care be taken to explicitly call .grass.bashrc et al # for non-interactive bash batch jobs? - userhome = os.getenv('HOME') # save original home - home = location # save .bashrc in $LOCATION - os.environ['HOME'] = home + userhome = os.getenv("HOME") # save original home + home = location # save .bashrc in $LOCATION + os.environ["HOME"] = home shell_rc_file = os.path.join(home, shrc) try_remove(shell_rc_file) - f = open(shell_rc_file, 'w') + f = open(shell_rc_file, "w") - if sh == 'zsh': - f.write('test -r {home}/.alias && source {home}/.alias\n'.format( - home=userhome)) + if sh == "zsh": + f.write("test -r {home}/.alias && source {home}/.alias\n".format(home=userhome)) else: f.write("test -r ~/.alias && . ~/.alias\n") - if os.getenv('ISISROOT'): + if os.getenv("ISISROOT"): # GRASS GIS and ISIS blend grass_name = "ISIS-GRASS" else: grass_name = "GRASS" - if sh == 'zsh': + if sh == "zsh": f.write("setopt PROMPT_SUBST\n") f.write("PS1='{name} : %1~ > '\n".format(name=grass_name)) else: - f.write("PS1='{name} {db_place}:\\W > '\n".format( - name=grass_name, version=GRASS_VERSION, db_place="$_GRASS_DB_PLACE")) + f.write( + "PS1='{name} {db_place}:\\W > '\n".format( + name=grass_name, version=GRASS_VERSION, db_place="$_GRASS_DB_PLACE" + ) + ) # TODO: have a function and/or module to test this mask2d_test = 'test -f "$MAPSET_PATH/cell/MASK"' mask3d_test = 'test -d "$MAPSET_PATH/grid3/RASTER3D_MASK"' specific_addition = "" - if sh == 'zsh': + if sh == "zsh": specific_addition = """ local z_lo=`g.gisenv get=LOCATION_NAME` local z_ms=`g.gisenv get=MAPSET` @@ -1864,7 +2043,9 @@ def sh_like_startup(location, location_name, grass_env_file, sh): fc -R _grass_old_mapset="$MAPSET_PATH" fi - """.format(sh_history=sh_history) + """.format( + sh_history=sh_history + ) elif sh == "bash": # Append existing history to file ("flush"). # Clear the (in-memory) history. @@ -1878,7 +2059,9 @@ def sh_like_startup(location, location_name, grass_env_file, sh): history -r _grass_old_mapset="$MAPSET_PATH" fi - """.format(sh_history=sh_history) + """.format( + sh_history=sh_history + ) # double curly brackets means single one for format function # setting LOCATION for backwards compatibility @@ -1899,50 +2082,51 @@ def sh_like_startup(location, location_name, grass_env_file, sh): both_masks=_("2D and 3D raster MASKs present"), mask2d=_("Raster MASK present"), mask3d=_("3D raster MASK present"), - mask2d_test=mask2d_test, mask3d_test=mask3d_test, - specific_addition=specific_addition - )) + mask2d_test=mask2d_test, + mask3d_test=mask3d_test, + specific_addition=specific_addition, + ) + ) - if sh == 'zsh': + if sh == "zsh": f.write('precmd() { eval "$PROMPT_COMMAND" }\n') - f.write('RPROMPT=\'${ZLOC}\'\n') + f.write("RPROMPT='${ZLOC}'\n") # this line was moved here from below .grass.bashrc to allow ~ and $HOME in # .grass.bashrc - f.write("export HOME=\"%s\"\n" % userhome) # restore user home path + f.write('export HOME="%s"\n' % userhome) # restore user home path # read other settings (aliases, ...) since environmental variables # have been already set by load_env(), see #3462 - for env_file in [os.path.join(userhome, grass_shrc), - grass_env_file]: + for env_file in [os.path.join(userhome, grass_shrc), grass_env_file]: if not os.access(env_file, os.R_OK): continue 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'): - f.write(line + '\n') + if MACOSX or not line.startswith("export"): + f.write(line + "\n") - f.write("export PATH=\"%s\"\n" % os.getenv('PATH')) + f.write('export PATH="%s"\n' % os.getenv("PATH")) # fix trac issue #3009 https://trac.osgeo.org/grass/ticket/3009 # re: failure to "Quit GRASS" from GUI - f.write("trap \"exit\" TERM\n") + f.write('trap "exit" TERM\n') f.close() - process = Popen([gpath("etc", "run"), os.getenv('SHELL')]) - os.environ['HOME'] = userhome + process = Popen([gpath("etc", "run"), os.getenv("SHELL")]) + os.environ["HOME"] = userhome return process def default_startup(location, location_name): """Start shell making no assumptions about what is supported in PS1""" if WINDOWS: - os.environ['PS1'] = "GRASS > " + os.environ["PS1"] = "GRASS > " # "$ETC/run" doesn't work at all??? - process = subprocess.Popen([os.getenv('SHELL')]) + process = subprocess.Popen([os.getenv("SHELL")]) else: - os.environ['PS1'] = "GRASS > " - process = Popen([gpath("etc", "run"), os.getenv('SHELL')]) + os.environ["PS1"] = "GRASS > " + process = Popen([gpath("etc", "run"), os.getenv("SHELL")]) return process @@ -1957,13 +2141,14 @@ def done_message(): def clean_temp(): message(_("Cleaning up temporary files...")) - nul = open(os.devnull, 'w') + nul = open(os.devnull, "w") call([gpath("etc", "clean_temp")], stdout=nul) nul.close() def clean_all(): from grass.script import setup as gsetup + # clean default sqlite db gsetup.clean_default_db() # remove leftover temp files @@ -1991,12 +2176,12 @@ def io_is_interactive(): def print_params(params): """Write compile flags and other configuration to stderr""" if not params: - params = ['arch', 'build', 'compiler', 'path', 'revision', 'version', 'date'] + params = ["arch", "build", "compiler", "path", "revision", "version", "date"] # check if we are dealing with parameters which require dev files dev_params = ["arch", "compiler", "build", "date"] if any([param in dev_params for param in params]): - plat = gpath('include', 'Make', 'Platform.make') + plat = gpath("include", "Make", "Platform.make") if not os.path.exists(plat): fatal(_("Please install the GRASS GIS development package")) fileplat = open(plat) @@ -2005,41 +2190,43 @@ def print_params(params): fileplat.close() for arg in params: - if arg == 'path': + if arg == "path": sys.stdout.write("%s\n" % GISBASE) - elif arg == 'arch': - val = grep('ARCH', linesplat) - sys.stdout.write("%s\n" % val[0].split('=')[1].strip()) - elif arg == 'build': - build = gpath('include', 'grass', 'confparms.h') + elif arg == "arch": + val = grep("ARCH", linesplat) + sys.stdout.write("%s\n" % val[0].split("=")[1].strip()) + elif arg == "build": + build = gpath("include", "grass", "confparms.h") filebuild = open(build) val = filebuild.readline() filebuild.close() sys.stdout.write("%s\n" % val.strip().strip('"').strip()) - elif arg == 'compiler': - val = grep('CC', linesplat) - sys.stdout.write("%s\n" % val[0].split('=')[1].strip()) - elif arg == 'revision': + elif arg == "compiler": + val = grep("CC", linesplat) + sys.stdout.write("%s\n" % val[0].split("=")[1].strip()) + elif arg == "revision": sys.stdout.write("@GRASS_VERSION_GIT@\n") - elif arg == 'svn_revision': - filerev = open(gpath('etc', 'VERSIONNUMBER')) - linerev = filerev.readline().rstrip('\n') + elif arg == "svn_revision": + filerev = open(gpath("etc", "VERSIONNUMBER")) + linerev = filerev.readline().rstrip("\n") filerev.close() try: - revision = linerev.split(' ')[1] + revision = linerev.split(" ")[1] sys.stdout.write("%s\n" % revision[1:]) except: sys.stdout.write("No SVN revision defined\n") - elif arg == 'version': + elif arg == "version": sys.stdout.write("%s\n" % GRASS_VERSION) - elif arg == 'date': + elif arg == "date": date_str = "#define GRASS_HEADERS_DATE " - gdate = gpath('include', 'grass', 'version.h') + gdate = gpath("include", "grass", "version.h") with open(gdate) as filegdate: for line in filegdate.readlines(): if line.startswith(date_str): - sys.stdout.write('{}\n'.format( - line.replace(date_str, '').lstrip()[1:-2]) # remove quotes + sys.stdout.write( + "{}\n".format( + line.replace(date_str, "").lstrip()[1:-2] + ) # remove quotes ) break else: @@ -2049,16 +2236,16 @@ def print_params(params): def get_username(): """Get name of the current user""" if WINDOWS: - user = os.getenv('USERNAME') + user = os.getenv("USERNAME") if not user: user = "user_name" else: - user = os.getenv('USER') + user = os.getenv("USER") if not user: - user = os.getenv('LOGNAME') + user = os.getenv("LOGNAME") if not user: try: - p = Popen(['whoami'], stdout=subprocess.PIPE) + p = Popen(["whoami"], stdout=subprocess.PIPE) s = p.stdout.read() p.wait() user = s.strip() @@ -2073,6 +2260,7 @@ def get_username(): class Parameters(object): """Structure to hold standard part of command line parameters""" + # we don't need to define any methods # pylint: disable=R0903 @@ -2231,9 +2419,10 @@ def validate_cmdline(params): if params.create_new and not params.mapset: fatal(_("Flag -c requires name of location or mapset")) if params.tmp_location and params.tmp_mapset: - fatal(_( - "Either --tmp-location or --tmp-mapset can be used, not both").format( - params.mapset) + fatal( + _("Either --tmp-location or --tmp-mapset can be used, not both").format( + params.mapset + ) ) if params.tmp_location and not params.geofile: fatal( @@ -2269,18 +2458,20 @@ def main(): default_gui = "wxpython" # explain what is happening in debug mode (visible only in debug mode) - debug("GRASS_DEBUG environmental variable is set. It is meant to be" - " an internal variable for debugging only this script.\n" - " Use 'g.gisenv set=\"DEBUG=[0-5]\"'" - " to turn GRASS GIS debug mode on if you wish to do so.") + debug( + "GRASS_DEBUG environmental variable is set. It is meant to be" + " an internal variable for debugging only this script.\n" + " Use 'g.gisenv set=\"DEBUG=[0-5]\"'" + " to turn GRASS GIS debug mode on if you wish to do so." + ) # 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 + os.environ["GIS_LOCK"] = gis_lock params = parse_cmdline(sys.argv, default_gui=default_gui) @@ -2305,7 +2496,6 @@ def main(): # Set the username user = get_username() - # Set shell (needs to be called before load_env()) sh, shellname = get_shell() grass_env_file = get_grass_env_file(sh, grass_config_dir) @@ -2335,8 +2525,10 @@ def main(): # First time user - GISRC is defined in the GRASS script if not os.access(gisrc, os.F_OK): - if grass_gui == 'text' and not params.mapset: - fatal(_("Unable to start GRASS GIS. You have the choice to:\n" + if grass_gui == "text" and not params.mapset: + fatal( + _( + "Unable to start GRASS GIS. You have the choice to:\n" " - Launch the graphical user interface with" " the '--gui' switch\n" " {cmd_name} --gui\n" @@ -2350,15 +2542,16 @@ def main(): " - Create manually the GISRC file ({gisrcrc})\n" " - 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)) + "See also: https://grass.osgeo.org/{cmd_name}/manuals/helptext.html" + ).format(cmd_name=CMD_NAME, gisrcrc=gisrcrc) + ) create_initial_gisrc(gisrc) message(_("Starting GRASS GIS...")) # Ensure GUI is set if params.batch_job or params.exit_grass: - grass_gui = 'text' + grass_gui = "text" else: if not grass_gui: # if GUI was not set previously (e.g. command line), @@ -2384,7 +2577,7 @@ def main(): grassdb, location, mapset = ga.ensure_demolocation() demo_mapset_usable = can_start_in_mapset( mapset_path=os.path.join(grassdb, location, mapset), - ignore_lock=params.force_gislock_removal + ignore_lock=params.force_gislock_removal, ) debug(f"demo_mapset_usable: {demo_mapset_usable}") if demo_mapset_usable: @@ -2396,25 +2589,32 @@ def main(): # User selects LOCATION and MAPSET if not set if not set_mapset_interactive(grass_gui): # No GUI available, update gisrc file - fatal(_("<{0}> requested, but not available. Run GRASS in text " + fatal( + _( + "<{0}> requested, but not available. Run GRASS in text " "mode (--text) or install missing package (usually " - "'grass-gui').").format(grass_gui)) + "'grass-gui')." + ).format(grass_gui) + ) else: # Mapset was specified in command line parameters. if params.tmp_location: # tmp loc requires other things to be set as well - set_mapset(gisrc=gisrc, geofile=params.geofile, - create_new=True, - tmp_location=params.tmp_location, tmpdir=tmpdir) + set_mapset( + gisrc=gisrc, + geofile=params.geofile, + create_new=True, + tmp_location=params.tmp_location, + tmpdir=tmpdir, + ) elif params.create_new and params.geofile: - set_mapset(gisrc=gisrc, arg=params.mapset, - geofile=params.geofile, create_new=True) + set_mapset( + gisrc=gisrc, arg=params.mapset, geofile=params.geofile, create_new=True + ) elif params.tmp_mapset: - set_mapset(gisrc=gisrc, arg=params.mapset, - tmp_mapset=params.tmp_mapset) + set_mapset(gisrc=gisrc, arg=params.mapset, tmp_mapset=params.tmp_mapset) else: - set_mapset(gisrc=gisrc, arg=params.mapset, - create_new=params.create_new) + set_mapset(gisrc=gisrc, arg=params.mapset, create_new=params.create_new) # Set GISDBASE, LOCATION_NAME, MAPSET, LOCATION from $GISRC # e.g. wxGUI startup screen writes to the gisrc file, @@ -2428,9 +2628,12 @@ def main(): location = mapset_settings.full_mapset # check and create .gislock file - lock_mapset(mapset_settings.full_mapset, user=user, - force_gislock_removal=params.force_gislock_removal, - grass_gui=grass_gui) + lock_mapset( + mapset_settings.full_mapset, + user=user, + force_gislock_removal=params.force_gislock_removal, + grass_gui=grass_gui, + ) # unlock the mapset which is current at the time of turning off # in case mapset was changed atexit.register(lambda: unlock_gisrc_mapset(gisrc, gisrcrc)) @@ -2461,27 +2664,32 @@ def main(): if use_shell: show_banner() say_hello() - show_info(shellname=shellname, - grass_gui=grass_gui, default_gui=default_gui) + show_info(shellname=shellname, grass_gui=grass_gui, default_gui=default_gui) if grass_gui == "wxpython": - message(_("Launching <%s> GUI in the background, please wait...") - % grass_gui) - if sh in ['csh', 'tcsh']: - shell_process = csh_startup(mapset_settings.full_mapset, - grass_env_file) - elif sh in ['zsh']: - shell_process = sh_like_startup(mapset_settings.full_mapset, - mapset_settings.location, - grass_env_file, - "zsh") - elif sh in ['bash', 'msh', 'cygwin']: - shell_process = sh_like_startup(mapset_settings.full_mapset, - mapset_settings.location, - grass_env_file, - "bash") + message( + _("Launching <%s> GUI in the background, please wait...") + % grass_gui + ) + if sh in ["csh", "tcsh"]: + shell_process = csh_startup(mapset_settings.full_mapset, grass_env_file) + elif sh in ["zsh"]: + shell_process = sh_like_startup( + mapset_settings.full_mapset, + mapset_settings.location, + grass_env_file, + "zsh", + ) + elif sh in ["bash", "msh", "cygwin"]: + shell_process = sh_like_startup( + mapset_settings.full_mapset, + mapset_settings.location, + grass_env_file, + "bash", + ) else: - shell_process = default_startup(mapset_settings.full_mapset, - mapset_settings.location) + shell_process = default_startup( + mapset_settings.full_mapset, mapset_settings.location + ) else: shell_process = None @@ -2490,14 +2698,14 @@ def main(): if shell_process: kv = {} - kv['PID'] = str(shell_process.pid) + kv["PID"] = str(shell_process.pid) # grass_prompt() tries to read gisrc while write_gisrc() is adding PID # to this file, so don't rewrite it; just append PID to make it # available to grass_prompt() at all times (PR #548) write_gisrc(kv, gisrc, append=True) exit_val = shell_process.wait() if exit_val != 0: - warning(_("Failed to start shell '%s'") % os.getenv('SHELL')) + warning(_("Failed to start shell '%s'") % os.getenv("SHELL")) else: gui_process.wait() @@ -2514,5 +2722,6 @@ def main(): if use_shell: done_message() -if __name__ == '__main__': + +if __name__ == "__main__": main()