Skip to content

Commit

Permalink
grass.script: Get GISBASE automatically in get_commands (#3683)
Browse files Browse the repository at this point in the history
* grass.script: Get GISBASE automatically in get_commands

The _grass.script.get_commands_ function requires GISBASE (more specifically, path to binary executables and scripts). The need for GISBASE prevents its use before a session (more specifically the runtime part of it) is created. This changes the function to get the GISBASE automatically when not set. It also adds the standard env parameter other functions have (which is useful mainly for tests).

* Add mock for tests
  • Loading branch information
wenzeslaus committed May 6, 2024
1 parent 77b3a16 commit 4ecb43e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 2 deletions.
14 changes: 12 additions & 2 deletions python/grass/script/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def _make_unicode(val, enc):
return decode(val, encoding=enc)


def get_commands():
def get_commands(*, env=None):
"""Create list of available GRASS commands to use when parsing
string from the command line
Expand All @@ -141,7 +141,17 @@ def get_commands():
['d.barscale', 'd.colorlist', 'd.colortable', 'd.correlate', 'd.erase']
"""
gisbase = os.environ["GISBASE"]
if not env:
env = os.environ
gisbase = env.get("GISBASE")

# Lazy-importing to avoid circular dependencies.
# pylint: disable=import-outside-toplevel
if not gisbase:
from grass.script.setup import get_install_path

gisbase = get_install_path()

cmd = list()
scripts = {".py": list()} if sys.platform == "win32" else {}

Expand Down
20 changes: 20 additions & 0 deletions python/grass/script/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Fixtures for grass.script"""

import pytest


@pytest.fixture
def mock_no_session(monkeypatch):
"""Set the environment variables as if there would be no background session.
Use with usefixtures (not as a paramter) to avoid warnings about an unused
parameter::
@pytest.mark.usefixtures("mock_no_session")
def test_session_handling():
pass
There may or may not be a session in the background (we don't check either way).
"""
monkeypatch.delenv("GISRC", raising=False)
monkeypatch.delenv("GISBASE", raising=False)
47 changes: 47 additions & 0 deletions python/grass/script/tests/grass_script_core_get_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Test grass.script.core.get_commands function"""

import sys

import pytest

import grass.script as gs


def common_test_code(executables_set, scripts_dict):
"""Assert results
Assuming we should always have some executables on path for this to pass a test.
"""
assert len(executables_set)
assert "g.region" in executables_set
if sys.platform == "win32":
assert len(scripts_dict.items())
# Just in case this is not a standard dictionary object.
assert len(scripts_dict.keys()) == len(scripts_dict.items())
assert "r.shade" in scripts_dict["py"]
else:
assert "r.shade" in executables_set


def test_no_explicit_session():
"""Test without explicit session setup here"""
executables_set, scripts_dict = gs.get_commands()
common_test_code(executables_set, scripts_dict)


@pytest.mark.usefixtures("mock_no_session")
def test_no_session_mocked():
"""Test with mocked no session"""
executables_set, scripts_dict = gs.get_commands()
common_test_code(executables_set, scripts_dict)


@pytest.mark.usefixtures("mock_no_session")
def test_in_session(tmp_path):
"""Test with mocked no session"""
# TODO: Use env=os.environ.copy()
project = tmp_path / "project"
gs.create_project(project)
with gs.setup.init(project) as session:
executables_set, scripts_dict = gs.get_commands(env=session.env)
common_test_code(executables_set, scripts_dict)

0 comments on commit 4ecb43e

Please sign in to comment.