Procházet zdrojové kódy

init/pythonlib: unified use of addonbase for mac (#2004)

- set default GRASS_ADDON_BASE for macOS to reflect the settings of
  GRASS app bundle
- for pythonlib grassscript.setup: use GRASS_ADDON_BASE if set, else
  fallback to defaults for each OS
- replaces hardcoded GRASS version as part file/dir names with a
  generated/dynamic version
nilason před 3 roky
rodič
revize
711cc2989f
4 změnil soubory, kde provedl 64 přidání a 42 odebrání
  1. 4 0
      lib/init/Makefile
  2. 25 22
      lib/init/grass.py
  3. 2 0
      python/grass/script/Makefile
  4. 33 20
      python/grass/script/setup.py

+ 4 - 0
lib/init/Makefile

@@ -70,6 +70,8 @@ endif
 	sed \
 	sed \
 	-e 's#@GISBASE@#$(RUN_GISBASE)#' \
 	-e 's#@GISBASE@#$(RUN_GISBASE)#' \
 	-e 's#@GRASS_VERSION_NUMBER@#$(GRASS_VERSION_NUMBER)#' \
 	-e 's#@GRASS_VERSION_NUMBER@#$(GRASS_VERSION_NUMBER)#' \
+	-e 's#@GRASS_VERSION_MAJOR@#$(GRASS_VERSION_MAJOR)#' \
+	-e 's#@GRASS_VERSION_MINOR@#$(GRASS_VERSION_MINOR)#' \
 	-e 's#@GRASS_VERSION_GIT@#$(GRASS_VERSION_GIT)#' \
 	-e 's#@GRASS_VERSION_GIT@#$(GRASS_VERSION_GIT)#' \
 	-e 's#@LD_LIBRARY_PATH_VAR@#$(LD_LIBRARY_PATH_VAR)#' \
 	-e 's#@LD_LIBRARY_PATH_VAR@#$(LD_LIBRARY_PATH_VAR)#' \
 	-e 's#@START_UP@#$(START_UP)#' \
 	-e 's#@START_UP@#$(START_UP)#' \
@@ -81,6 +83,8 @@ $(ARCH_DISTDIR)/$(START_UP).tmp: grass.py
 	rm -f $@
 	rm -f $@
 	sed \
 	sed \
 	-e 's#@GRASS_VERSION_NUMBER@#$(GRASS_VERSION_NUMBER)#' \
 	-e 's#@GRASS_VERSION_NUMBER@#$(GRASS_VERSION_NUMBER)#' \
+	-e 's#@GRASS_VERSION_MAJOR@#$(GRASS_VERSION_MAJOR)#' \
+	-e 's#@GRASS_VERSION_MINOR@#$(GRASS_VERSION_MINOR)#' \
 	-e 's#@GRASS_VERSION_GIT@#$(GRASS_VERSION_GIT)#' \
 	-e 's#@GRASS_VERSION_GIT@#$(GRASS_VERSION_GIT)#' \
 	-e 's#@START_UP@#$(START_UP)#' \
 	-e 's#@START_UP@#$(START_UP)#' \
 	-e 's#@GRASS_CONFIG_DIR@#$(GRASS_CONFIG_DIR)#' \
 	-e 's#@GRASS_CONFIG_DIR@#$(GRASS_CONFIG_DIR)#' \

+ 25 - 22
lib/init/grass.py

@@ -92,13 +92,15 @@ else:
     os.environ["GISBASE"] = GISBASE
     os.environ["GISBASE"] = GISBASE
 CMD_NAME = "@START_UP@"
 CMD_NAME = "@START_UP@"
 GRASS_VERSION = "@GRASS_VERSION_NUMBER@"
 GRASS_VERSION = "@GRASS_VERSION_NUMBER@"
+GRASS_VERSION_MAJOR = "@GRASS_VERSION_MAJOR@"
+GRASS_VERSION_MINOR = "@GRASS_VERSION_MINOR@"
 LD_LIBRARY_PATH_VAR = "@LD_LIBRARY_PATH_VAR@"
 LD_LIBRARY_PATH_VAR = "@LD_LIBRARY_PATH_VAR@"
 CONFIG_PROJSHARE = os.environ.get("GRASS_PROJSHARE", "@CONFIG_PROJSHARE@")
 CONFIG_PROJSHARE = os.environ.get("GRASS_PROJSHARE", "@CONFIG_PROJSHARE@")
 
 
 # Get the system name
 # Get the system name
-WINDOWS = sys.platform == "win32"
-CYGWIN = "cygwin" in sys.platform
-MACOSX = "darwin" in sys.platform
+WINDOWS = sys.platform.startswith("win")
+CYGWIN = sys.platform.startswith("cygwin")
+MACOS = sys.platform.startswith("darwin")
 
 
 
 
 def decode(bytes_, encoding=ENCODING):
 def decode(bytes_, encoding=ENCODING):
@@ -440,8 +442,8 @@ def get_grass_config_dir():
     Configuration directory is for example used for grass env file
     Configuration directory is for example used for grass env file
     (the one which caries mapset settings from session to session).
     (the one which caries mapset settings from session to session).
     """
     """
-    if sys.platform == "win32":
-        grass_config_dirname = "GRASS8"
+    if WINDOWS:
+        grass_config_dirname = f"GRASS{GRASS_VERSION_MAJOR}"
         win_conf_path = os.getenv("APPDATA")
         win_conf_path = os.getenv("APPDATA")
         # this can happen with some strange settings
         # this can happen with some strange settings
         if not win_conf_path:
         if not win_conf_path:
@@ -460,7 +462,7 @@ def get_grass_config_dir():
             )
             )
         directory = os.path.join(win_conf_path, grass_config_dirname)
         directory = os.path.join(win_conf_path, grass_config_dirname)
     else:
     else:
-        grass_config_dirname = ".grass8"
+        grass_config_dirname = f".grass{GRASS_VERSION_MAJOR}"
         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):
     if not os.path.isdir(directory):
         try:
         try:
@@ -490,10 +492,9 @@ def create_tmp(user, gis_lock):
     if not tmp:
     if not tmp:
         tmp = tempfile.gettempdir()
         tmp = tempfile.gettempdir()
 
 
+    tmpdir_name = f"grass{GRASS_VERSION_MAJOR}-{user}-{gis_lock}"
     if tmp:
     if tmp:
-        tmpdir = os.path.join(
-            tmp, "grass8-%(user)s-%(lock)s" % {"user": user, "lock": gis_lock}
-        )
+        tmpdir = os.path.join(tmp, tmpdir_name)
         try:
         try:
             os.mkdir(tmpdir, 0o700)
             os.mkdir(tmpdir, 0o700)
         except:  # noqa: E722
         except:  # noqa: E722
@@ -502,9 +503,7 @@ def create_tmp(user, gis_lock):
     if not tmp:
     if not tmp:
         for ttmp in ("/tmp", "/var/tmp", "/usr/tmp"):
         for ttmp in ("/tmp", "/var/tmp", "/usr/tmp"):
             tmp = ttmp
             tmp = ttmp
-            tmpdir = os.path.join(
-                tmp, "grass8-%(user)s-%(lock)s" % {"user": user, "lock": gis_lock}
-            )
+            tmpdir = os.path.join(tmp, tmpdir_name)
             try:
             try:
                 os.mkdir(tmpdir, 0o700)
                 os.mkdir(tmpdir, 0o700)
             except:  # noqa: E722
             except:  # noqa: E722
@@ -514,11 +513,9 @@ def create_tmp(user, gis_lock):
 
 
     if not tmp:
     if not tmp:
         fatal(
         fatal(
-            _(
-                "Unable to create temporary directory <grass8-%(user)s-"
-                "%(lock)s>! Exiting."
+            _("Unable to create temporary directory <{tmpdir_name}>! Exiting.").format(
+                tmpdir_name=tmpdir_name
             )
             )
-            % {"user": user, "lock": gis_lock}
         )
         )
 
 
     # promoting the variable even if it was not defined before
     # promoting the variable even if it was not defined before
@@ -716,7 +713,13 @@ def set_paths(grass_config_dir):
     # addons (base)
     # addons (base)
     addon_base = os.getenv("GRASS_ADDON_BASE")
     addon_base = os.getenv("GRASS_ADDON_BASE")
     if not addon_base:
     if not addon_base:
-        addon_base = os.path.join(grass_config_dir, "addons")
+        if MACOS:
+            version = f"{GRASS_VERSION_MAJOR}.{GRASS_VERSION_MINOR}"
+            addon_base = os.path.join(
+                os.getenv("HOME"), "Library", "GRASS", version, "Addons"
+            )
+        else:
+            addon_base = os.path.join(grass_config_dir, "addons")
         os.environ["GRASS_ADDON_BASE"] = addon_base
         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, "scripts"), "PATH")
@@ -817,7 +820,7 @@ def set_browser():
     # GRASS_HTML_BROWSER
     # GRASS_HTML_BROWSER
     browser = os.getenv("GRASS_HTML_BROWSER")
     browser = os.getenv("GRASS_HTML_BROWSER")
     if not browser:
     if not browser:
-        if MACOSX:
+        if MACOS:
             # OSX doesn't execute browsers from the shell PATH - route through a
             # OSX doesn't execute browsers from the shell PATH - route through a
             # script
             # script
             browser = gpath("etc", "html_browser_mac.sh")
             browser = gpath("etc", "html_browser_mac.sh")
@@ -852,7 +855,7 @@ def set_browser():
                     browser = b
                     browser = b
                     break
                     break
 
 
-    elif MACOSX:
+    elif MACOS:
         # OSX doesn't execute browsers from the shell PATH - route through a
         # OSX doesn't execute browsers from the shell PATH - route through a
         # script
         # script
         os.environ["GRASS_HTML_BROWSER_MACOSX"] = "-b %s" % browser
         os.environ["GRASS_HTML_BROWSER_MACOSX"] = "-b %s" % browser
@@ -886,7 +889,7 @@ MAPSET: <UNKNOWN>
 def check_gui(expected_gui):
 def check_gui(expected_gui):
     grass_gui = expected_gui
     grass_gui = expected_gui
     # Check if we are running X windows by checking the DISPLAY variable
     # 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 MACOS:
         # Check if python is working properly
         # Check if python is working properly
         if expected_gui in ("wxpython", "gtext"):
         if expected_gui in ("wxpython", "gtext"):
             nul = open(os.devnull, "w")
             nul = open(os.devnull, "w")
@@ -1656,7 +1659,7 @@ def get_shell():
 
 
     # cygwin has many problems with the shell setup
     # cygwin has many problems with the shell setup
     # below, so i hardcoded everything here.
     # below, so i hardcoded everything here.
-    if sys.platform == "cygwin":
+    if CYGWIN:
         sh = "CYGWIN"
         sh = "CYGWIN"
         shellname = "GNU Bash (Cygwin)"
         shellname = "GNU Bash (Cygwin)"
         os.environ["SHELL"] = "/usr/bin/bash.exe"
         os.environ["SHELL"] = "/usr/bin/bash.exe"
@@ -2063,7 +2066,7 @@ PROMPT_COMMAND=grass_prompt\n""".format(
         for line in readfile(env_file).splitlines():
         for line in readfile(env_file).splitlines():
             # Bug related to OS X "SIP", see
             # Bug related to OS X "SIP", see
             # https://trac.osgeo.org/grass/ticket/3462#comment:13
             # https://trac.osgeo.org/grass/ticket/3462#comment:13
-            if MACOSX or not line.startswith("export"):
+            if MACOS or not line.startswith("export"):
                 f.write(line + "\n")
                 f.write(line + "\n")
 
 
     f.write('export PATH="%s"\n' % os.getenv("PATH"))
     f.write('export PATH="%s"\n' % os.getenv("PATH"))

+ 2 - 0
python/grass/script/Makefile

@@ -26,4 +26,6 @@ $(DSTDIR)/setup.py: setup.py.tmp | $(DSTDIR)
 setup.py.tmp: setup.py
 setup.py.tmp: setup.py
 	sed \
 	sed \
 	-e 's#@LD_LIBRARY_PATH_VAR@#$(LD_LIBRARY_PATH_VAR)#' \
 	-e 's#@LD_LIBRARY_PATH_VAR@#$(LD_LIBRARY_PATH_VAR)#' \
+	-e 's#@GRASS_VERSION_MAJOR@#$(GRASS_VERSION_MAJOR)#' \
+	-e 's#@GRASS_VERSION_MINOR@#$(GRASS_VERSION_MINOR)#' \
 	$< > $@
 	$< > $@

+ 33 - 20
python/grass/script/setup.py

@@ -87,7 +87,11 @@ import subprocess
 import sys
 import sys
 import tempfile as tmpfile
 import tempfile as tmpfile
 
 
-windows = sys.platform == "win32"
+WINDOWS = sys.platform.startswith("win")
+MACOS = sys.platform.startswith("darwin")
+
+VERSION_MAJOR = "@GRASS_VERSION_MAJOR@"
+VERSION_MINOR = "@GRASS_VERSION_MINOR@"
 
 
 
 
 def write_gisrc(dbase, location, mapset):
 def write_gisrc(dbase, location, mapset):
@@ -196,26 +200,35 @@ def setup_runtime_env(gisbase):
     gisbase = os.fspath(gisbase)
     gisbase = os.fspath(gisbase)
     # Set GISBASE
     # Set GISBASE
     os.environ["GISBASE"] = gisbase
     os.environ["GISBASE"] = gisbase
-    mswin = sys.platform.startswith("win")
+
     # define PATH
     # define PATH
-    os.environ["PATH"] += os.pathsep + os.path.join(gisbase, "bin")
-    os.environ["PATH"] += os.pathsep + os.path.join(gisbase, "scripts")
-    if mswin:  # added for winGRASS
-        os.environ["PATH"] += os.pathsep + os.path.join(gisbase, "extrabin")
+    path_addition = os.pathsep + os.path.join(gisbase, "bin")
+    path_addition += os.pathsep + os.path.join(gisbase, "scripts")
+    if WINDOWS:
+        path_addition += os.pathsep + os.path.join(gisbase, "extrabin")
 
 
-    # add addons to the PATH
+    # add addons to the PATH, use GRASS_ADDON_BASE if set
     # copied and simplified from lib/init/grass.py
     # copied and simplified from lib/init/grass.py
-    if mswin:
-        config_dirname = "GRASS8"
-        config_dir = os.path.join(os.getenv("APPDATA"), config_dirname)
-    else:
-        config_dirname = ".grass8"
-        config_dir = os.path.join(os.getenv("HOME"), config_dirname)
-    addon_base = os.path.join(config_dir, "addons")
-    os.environ["GRASS_ADDON_BASE"] = addon_base
-    if not mswin:
-        os.environ["PATH"] += os.pathsep + os.path.join(addon_base, "scripts")
-    os.environ["PATH"] += os.pathsep + os.path.join(addon_base, "bin")
+    addon_base = os.getenv("GRASS_ADDON_BASE")
+    if not addon_base:
+        if WINDOWS:
+            config_dirname = f"GRASS{VERSION_MAJOR}"
+            addon_base = os.path.join(os.getenv("APPDATA"), config_dirname, "addons")
+        elif MACOS:
+            version = f"{VERSION_MAJOR}.{VERSION_MINOR}"
+            addon_base = os.path.join(
+                os.getenv("HOME"), "Library", "GRASS", version, "Addons"
+            )
+        else:
+            config_dirname = f".grass{VERSION_MAJOR}"
+            addon_base = os.path.join(os.getenv("HOME"), config_dirname, "addons")
+        os.environ["GRASS_ADDON_BASE"] = addon_base
+
+    if not WINDOWS:
+        path_addition += os.pathsep + os.path.join(addon_base, "scripts")
+    path_addition += os.pathsep + os.path.join(addon_base, "bin")
+
+    os.environ["PATH"] = path_addition + os.pathsep + os.getenv("PATH")
 
 
     # define LD_LIBRARY_PATH
     # define LD_LIBRARY_PATH
     if "@LD_LIBRARY_PATH_VAR@" not in os.environ:
     if "@LD_LIBRARY_PATH_VAR@" not in os.environ:
@@ -224,7 +237,7 @@ def setup_runtime_env(gisbase):
 
 
     # Set GRASS_PYTHON and PYTHONPATH to find GRASS Python modules
     # Set GRASS_PYTHON and PYTHONPATH to find GRASS Python modules
     if not os.getenv("GRASS_PYTHON"):
     if not os.getenv("GRASS_PYTHON"):
-        if sys.platform == "win32":
+        if WINDOWS:
             os.environ["GRASS_PYTHON"] = "python3.exe"
             os.environ["GRASS_PYTHON"] = "python3.exe"
         else:
         else:
             os.environ["GRASS_PYTHON"] = "python3"
             os.environ["GRASS_PYTHON"] = "python3"
@@ -348,7 +361,7 @@ def clean_default_db():
 
 
 def call(cmd, **kwargs):
 def call(cmd, **kwargs):
     """Wrapper for subprocess.call to deal with platform-specific issues"""
     """Wrapper for subprocess.call to deal with platform-specific issues"""
-    if windows:
+    if WINDOWS:
         kwargs["shell"] = True
         kwargs["shell"] = True
     return subprocess.call(cmd, **kwargs)
     return subprocess.call(cmd, **kwargs)