浏览代码

init: Create demolocation in grass.py, not wxGUI gis_set.py (#1208)

* Moves functionality from gis_set.py to grass.py.
* Moves library functions from wxGUI startup to new grass.app package.
* Opens the old startup when the PERMANENT of demolocation is not usable (as before).
Vaclav Petras 4 年之前
父节点
当前提交
28876fe653
共有 6 个文件被更改,包括 92 次插入49 次删除
  1. 0 14
      gui/wxpython/gis_set.py
  2. 39 18
      lib/init/grass.py
  3. 1 1
      lib/python/Makefile
  4. 19 0
      lib/python/app/Makefile
  5. 1 0
      lib/python/app/__init__.py
  6. 32 16
      gui/wxpython/startup/utils.py

+ 0 - 14
gui/wxpython/gis_set.py

@@ -41,10 +41,6 @@ from grass.grassdb.checks import get_lockfile_if_present
 
 from core.gcmd import GError, RunCommand
 from core.utils import GetListOfLocations, GetListOfMapsets
-from startup.utils import (
-    get_possible_database_path,
-    create_database_directory,
-    create_startup_location_in_grassdb)
 from startup.guiutils import (SetSessionMapset,
                               create_mapset_interactively,
                               create_location_interactively,
@@ -516,16 +512,6 @@ class GRASSStartup(wx.Frame):
         if self.GetRCValue("LOCATION_NAME") != "<UNKNOWN>":
             return
         path = get_possible_database_path()
-
-        # If nothing found, try to create GRASS directory and copy startup loc
-        if path is None:
-            grassdb = create_database_directory()
-            location = "world_latlong_wgs84"
-            if create_startup_location_in_grassdb(grassdb,
-                                                  location):
-                self.SetLocation(grassdb, location, "PERMANENT")
-                self.ExitSuccessfully()
-
         if path:
             try:
                 self.tgisdbase.SetValue(path)

+ 39 - 18
lib/init/grass.py

@@ -565,6 +565,17 @@ def write_gisrc(kv, filename, append=False):
     f.close()
 
 
+def set_mapset_to_gisrc(gisrc, grassdb, location, mapset):
+    if os.access(gisrc, os.R_OK):
+        kv = read_gisrc(gisrc)
+    else:
+        kv = {}
+    kv['GISDBASE'] = grassdb
+    kv['LOCATION_NAME'] = location
+    kv['MAPSET'] = mapset
+    write_gisrc(kv, gisrc)
+
+
 def read_gui(gisrc, default_gui):
     grass_gui = None
     # At this point the GRASS user interface variable has been set from the
@@ -1050,16 +1061,7 @@ def set_mapset(gisrc, arg=None, geofile=None, create_new=False,
                     s = readfile(os.path.join(gisdbase, location_name,
                                               "PERMANENT", "DEFAULT_WIND"))
                     writefile(os.path.join(path, "WIND"), s)
-
-        if os.access(gisrc, os.R_OK):
-            kv = read_gisrc(gisrc)
-        else:
-            kv = {}
-
-        kv['GISDBASE'] = gisdbase
-        kv['LOCATION_NAME'] = location_name
-        kv['MAPSET'] = mapset
-        write_gisrc(kv, gisrc)
+        set_mapset_to_gisrc(gisrc, gisdbase, location_name, mapset)
     else:
         fatal(_("GRASS GIS database directory, location and mapset"
                 " not set properly."
@@ -1661,6 +1663,7 @@ def start_gui(grass_gui):
     debug("GRASS GUI should be <%s>" % grass_gui)
     # Check for gui interface
     if grass_gui == "wxpython":
+        # TODO: report failures
         return Popen([os.getenv('GRASS_PYTHON'), wxpath("wxgui.py")])
     return None
 
@@ -2368,18 +2371,36 @@ def main():
 
     # Parsing argument to get LOCATION
     if not params.mapset and not params.tmp_location:
+        # Mapset is not specified in command line arguments.
         last_mapset_usable = can_start_in_gisrc_mapset(
             gisrc=gisrc, ignore_lock=params.force_gislock_removal
         )
-        # Try interactive startup
-        # User selects LOCATION and MAPSET if not set
-        if not last_mapset_usable and not set_mapset_interactive(grass_gui):
-            # No GUI available, update gisrc file
-            fatal(_("<{0}> requested, but not available. Run GRASS in text "
-                    "mode (--text) or install missing package (usually "
-                    "'grass-gui').").format(grass_gui))
+        debug(f"last_mapset_usable: {last_mapset_usable}")
+        if not last_mapset_usable:
+            import grass.app as ga
+            from grass.grassdb.checks import can_start_in_mapset
+
+            # Try to use demolocation
+            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
+            )
+            debug(f"demo_mapset_usable: {demo_mapset_usable}")
+            if demo_mapset_usable:
+                set_mapset_to_gisrc(
+                    gisrc=gisrc, grassdb=grassdb, location=location, mapset=mapset
+                )
+            else:
+                # Try interactive startup
+                # 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 "
+                            "mode (--text) or install missing package (usually "
+                            "'grass-gui').").format(grass_gui))
     else:
-        # Try non-interactive start up
+        # 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,

+ 1 - 1
lib/python/Makefile

@@ -5,7 +5,7 @@ include $(MODULE_TOPDIR)/include/Make/Python.make
 
 PYDIR = $(ETC)/python/grass
 
-SUBDIRS = exceptions script ctypes grassdb temporal pygrass pydispatch imaging gunittest bandref
+SUBDIRS = app exceptions script ctypes grassdb temporal pygrass pydispatch imaging gunittest bandref
 
 default: $(PYDIR)/__init__.py
 	$(MAKE) subdirs

+ 19 - 0
lib/python/app/Makefile

@@ -0,0 +1,19 @@
+MODULE_TOPDIR = ../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+
+DSTDIR = $(ETC)/python/grass/app
+
+MODULES = data
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+default: $(PYFILES) $(PYCFILES)
+
+$(DSTDIR):
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@

+ 1 - 0
lib/python/app/__init__.py

@@ -0,0 +1 @@
+from .data import *

+ 32 - 16
gui/wxpython/startup/utils.py

@@ -1,28 +1,25 @@
-"""
-@package startup.utils
-
-@brief General GUI-independent utilities for GUI startup of GRASS GIS
+"""Provides functions for the main GRASS GIS executable
 
-(C) 2017-2018 by Vaclav Petras the GRASS Development Team
+(C) 2020 by Vaclav Petras and the GRASS Development Team
 
-This program is free software under the GNU General Public License
-(>=v2). Read the file COPYING that comes with GRASS for details.
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
 
-@author Vaclav Petras <wenzeslaus gmail com>
-@author Linda Kladivova <l.kladivova@seznam.cz>
+.. sectionauthor:: Vaclav Petras <wenzeslaus gmail com>
+.. sectionauthor:: Linda Kladivova <l.kladivova seznam cz>
 
-This file should not use (import) anything from GUI code (wx or wxGUI).
-This can potentially be part of the Python library (i.e. it needs to
-solve the errors etc. in a general manner).
+This is not a stable part of the API. Use at your own risk.
 """
 
-
 import os
 import tempfile
 import getpass
 import sys
 from shutil import copytree, ignore_patterns
 
+from grass.grassdb.checks import is_location_valid
+
 
 def get_possible_database_path():
     """Looks for directory 'grassdata' (case-insensitive) in standard
@@ -113,8 +110,11 @@ def _copy_startup_location(startup_location, location_in_grassdb):
     """
     # Copy source startup location into GRASS database
     try:
-        copytree(startup_location, location_in_grassdb,
-                 ignore=ignore_patterns('*.tmpl', 'Makefile*'))
+        copytree(
+            startup_location,
+            location_in_grassdb,
+            ignore=ignore_patterns("*.tmpl", "Makefile*"),
+        )
         return True
     except (IOError, OSError):
         pass
@@ -129,7 +129,6 @@ def create_startup_location_in_grassdb(grassdatabase, startup_location_name):
     Returns False if there is no location to copy in the installation
     or copying failed.
     """
-
     # Find out if startup location exists
     startup_location = _get_startup_location_in_distribution()
     if not startup_location:
@@ -140,3 +139,20 @@ def create_startup_location_in_grassdb(grassdatabase, startup_location_name):
     if _copy_startup_location(startup_location, location_in_grassdb):
         return True
     return False
+
+
+def ensure_demolocation():
+    """Ensure that demolocation exists
+
+    Creates both database directory and location if needed.
+
+    Returns the db, location name, and preferred mapset of the demolocation.
+    """
+    grassdb = get_possible_database_path()
+    # If nothing found, try to create GRASS directory and copy startup loc
+    if grassdb is None:
+        grassdb = create_database_directory()
+    location = "world_latlong_wgs84"
+    if not is_location_valid(grassdb, location):
+        create_startup_location_in_grassdb(grassdb, location)
+    return (grassdb, location, "PERMANENT")