From ad30eb7ac6780ea079387f1b4ca3b20d8420b94e Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Tue, 30 Nov 2021 17:14:20 -0500 Subject: [PATCH] init: Output value for sys.path in config (#1835) With this addition, running grass --config python_path outputs the value needed for sys.path. This is useful in Python where sys.path needs to be set up correctly before the grass package can be imported. Instead of having to hardcode the etc/python part of the path, user can (optionally) obtain the full path from the new parameter resulting in a more general code which requires just passing a result of call stripped from the white spaces. This is especially interesting in combination with #1838 after which GISBASE environmental variable does not have to be set up before for importing grass.script package, so setting up sys.path is the only step user needs to do before that. Additionally, with #1829 (and #1979) the installation path (GISBASE) can be determined automatically from the path to the grass.script.setup module (file), the executable (if it is called grass), or from a user-provided executable which was be called (by the user) to obtain python_path. The new setup method is now used in the notebooks. This simplifoes usage documentaion in setup.py module. No GISBASE is needed. No explicit error checking (errors are printed and/or raised automatically). sys.path now needs to be str/unicode. --- doc/notebooks/basic_example.ipynb | 6 ++--- .../basic_example_grass_jupyter.ipynb | 6 ++--- doc/notebooks/grass_jupyter.ipynb | 8 +++--- doc/notebooks/hydrology.ipynb | 6 ++--- doc/notebooks/solar_potential.ipynb | 6 ++--- doc/notebooks/viewshed_analysis.ipynb | 6 ++--- lib/init/grass.py | 15 +++++++++-- python/grass/script/setup.py | 25 ++++--------------- 8 files changed, 37 insertions(+), 41 deletions(-) diff --git a/doc/notebooks/basic_example.ipynb b/doc/notebooks/basic_example.ipynb index 7ed35f09c01..62d4214dcd1 100644 --- a/doc/notebooks/basic_example.ipynb +++ b/doc/notebooks/basic_example.ipynb @@ -35,9 +35,9 @@ "from IPython.display import Image\n", "\n", "# Ask GRASS GIS where its Python packages are.\n", - "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n", - "os.environ[\"GISBASE\"] = gisbase\n", - "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n", + "sys.path.append(\n", + " subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n", + ")\n", "\n", "# Import the GRASS GIS packages we need.\n", "import grass.script as gs\n", diff --git a/doc/notebooks/basic_example_grass_jupyter.ipynb b/doc/notebooks/basic_example_grass_jupyter.ipynb index 43452213648..e7dbcc363de 100644 --- a/doc/notebooks/basic_example_grass_jupyter.ipynb +++ b/doc/notebooks/basic_example_grass_jupyter.ipynb @@ -37,9 +37,9 @@ "import sys\n", "\n", "# Ask GRASS GIS where its Python packages are.\n", - "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n", - "os.environ[\"GISBASE\"] = gisbase\n", - "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n", + "sys.path.append(\n", + " subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n", + ")\n", "\n", "# Import the GRASS GIS packages we need.\n", "import grass.script as gs\n", diff --git a/doc/notebooks/grass_jupyter.ipynb b/doc/notebooks/grass_jupyter.ipynb index d47231c1931..e3cefe3b3ba 100644 --- a/doc/notebooks/grass_jupyter.ipynb +++ b/doc/notebooks/grass_jupyter.ipynb @@ -30,10 +30,10 @@ "import subprocess\n", "import sys\n", "\n", - "# Add GRASS to path\n", - "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n", - "os.environ[\"GISBASE\"] = gisbase\n", - "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n", + "# Ask GRASS GIS where its Python packages are.\n", + "sys.path.append(\n", + " subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n", + ")\n", "\n", "# Import GRASS packages\n", "import grass.script as gs\n", diff --git a/doc/notebooks/hydrology.ipynb b/doc/notebooks/hydrology.ipynb index 0b49afcc766..c0c42db80e7 100644 --- a/doc/notebooks/hydrology.ipynb +++ b/doc/notebooks/hydrology.ipynb @@ -34,9 +34,9 @@ "from collections import defaultdict\n", "\n", "# Ask GRASS GIS where its Python packages are.\n", - "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n", - "os.environ[\"GISBASE\"] = gisbase\n", - "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n", + "sys.path.append(\n", + " subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n", + ")\n", "\n", "# Import the GRASS GIS packages we need.\n", "import grass.script as gs\n", diff --git a/doc/notebooks/solar_potential.ipynb b/doc/notebooks/solar_potential.ipynb index 21b66ccd4ee..04a268a7381 100644 --- a/doc/notebooks/solar_potential.ipynb +++ b/doc/notebooks/solar_potential.ipynb @@ -33,9 +33,9 @@ "import sys\n", "\n", "# Ask GRASS GIS where its Python packages are.\n", - "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n", - "os.environ[\"GISBASE\"] = gisbase\n", - "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n", + "sys.path.append(\n", + " subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n", + ")\n", "\n", "# Import the GRASS GIS packages we need.\n", "import grass.script as gs\n", diff --git a/doc/notebooks/viewshed_analysis.ipynb b/doc/notebooks/viewshed_analysis.ipynb index b048c38bdcb..16fd38e1447 100644 --- a/doc/notebooks/viewshed_analysis.ipynb +++ b/doc/notebooks/viewshed_analysis.ipynb @@ -35,9 +35,9 @@ "import sys\n", "\n", "# Ask GRASS GIS where its Python packages are.\n", - "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n", - "os.environ[\"GISBASE\"] = gisbase\n", - "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n", + "sys.path.append(\n", + " subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n", + ")\n", "\n", "# Import the GRASS GIS packages we need.\n", "import grass.script as gs\n", diff --git a/lib/init/grass.py b/lib/init/grass.py index 46aab601526..84053804713 100755 --- a/lib/init/grass.py +++ b/lib/init/grass.py @@ -2133,9 +2133,18 @@ def io_is_interactive(): def print_params(params): - """Write compile flags and other configuration to stderr""" + """Write compile flags and other configuration to stdout""" if not params: - params = ["arch", "build", "compiler", "path", "revision", "version", "date"] + params = [ + "arch", + "build", + "compiler", + "path", + "python_path", + "revision", + "version", + "date", + ] # check if we are dealing with parameters which require dev files dev_params = ["arch", "compiler", "build", "date"] @@ -2151,6 +2160,8 @@ def print_params(params): for arg in params: if arg == "path": sys.stdout.write("%s\n" % GISBASE) + elif arg in ["python_path", "python-path"]: + sys.stdout.write("%s\n" % gpath("etc", "python")) elif arg == "arch": val = grep("ARCH", linesplat) sys.stdout.write("%s\n" % val[0].split("=")[1].strip()) diff --git a/python/grass/script/setup.py b/python/grass/script/setup.py index 3098be5af83..d9e6feae916 100644 --- a/python/grass/script/setup.py +++ b/python/grass/script/setup.py @@ -36,34 +36,19 @@ # TODO: this have to be checked, maybe unix way is good enough grass8bin = '/Applications/GRASS/GRASS-8.0.app/' - # query GRASS GIS itself for its GISBASE - startcmd = [grass8bin, '--config', 'path'] - try: - p = subprocess.Popen(startcmd, shell=False, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = p.communicate() - except OSError as error: - sys.exit("ERROR: Cannot find GRASS GIS start script" - " {cmd}: {error}".format(cmd=startcmd[0], error=error)) - if p.returncode != 0: - sys.exit("ERROR: Issues running GRASS GIS start script" - " {cmd}: {error}" - .format(cmd=' '.join(startcmd), error=err)) - gisbase = out.strip(os.linesep) - - # set GISBASE environment variable - os.environ['GISBASE'] = gisbase + # query GRASS GIS itself for its Python package path + grass_cmd = [grass8bin, "--config", "python_path"] + process = subprocess.run(grass_cmd, check=True, text=True, stdout=subprocess.PIPE) # define GRASS-Python environment - grass_pydir = os.path.join(gisbase, "etc", "python") - sys.path.append(grass_pydir) + sys.path.append(process.stdout.strip()) # import (some) GRASS Python bindings import grass.script as gs import grass.script.setup as gsetup # launch session - rcfile = gsetup.init(gisdb, location, mapset, grass_path=gisbase) + rcfile = gsetup.init(gisdb, location, mapset) # example calls gs.message('Current GRASS GIS 8 environment:')