diff --git a/python/grass/script/core.py b/python/grass/script/core.py index 6ee8e0f987f..7cc50b58733 100644 --- a/python/grass/script/core.py +++ b/python/grass/script/core.py @@ -237,6 +237,18 @@ def scan(gisbase, directory): for directory in ("bin", "scripts"): scan(gisbase, directory) + # Add addon path if it exists + if env.get("GRASS_ADDON_BASE"): + addon_base = env["GRASS_ADDON_BASE"] + scan(addon_base, "bin") + if not sys.platform.startswith("win"): + scan(addon_base, "scripts") + + if env.get("GRASS_ADDON_PATH"): + for path in env["GRASS_ADDON_PATH"].split(os.pathsep): + if path: + scan(path, "") + return set(cmd), scripts diff --git a/python/grass/script/tests/grass_script_core_get_commands_test.py b/python/grass/script/tests/grass_script_core_get_commands_test.py index 27c94c7f62d..b710a65a304 100644 --- a/python/grass/script/tests/grass_script_core_get_commands_test.py +++ b/python/grass/script/tests/grass_script_core_get_commands_test.py @@ -2,7 +2,7 @@ import os import sys - +import stat import pytest import grass.script as gs @@ -65,3 +65,31 @@ def test_in_session(tmp_path): with gs.setup.init(project, env=os.environ.copy()) as session: executables_set, scripts_dict = gs.get_commands(env=session.env) common_test_code(executables_set, scripts_dict) + + +def test_addon_path_multiple_dirs(tmp_path): + """Test that get_commands scans multiple directories in GRASS_ADDON_PATH""" + + test_dirs = [ + (tmp_path / "addon_a", "my_custom_cmd_a"), + (tmp_path / "addon_b", "my_custom_cmd_b"), + ] + + ext = ".py" if sys.platform == "win32" else "" + + for path, cmd_name in test_dirs: + path.mkdir() + file_path = path / f"{cmd_name}{ext}" + file_path.write_text( + "#!/usr/bin/env python3\nprint('Test ADDON PATH')", encoding="utf-8" + ) + file_path.chmod(stat.S_IRWXU) + + new_path = os.pathsep.join(str(p) for p, _ in test_dirs) + env = os.environ.copy() + env["GRASS_ADDON_PATH"] = new_path + + executables_set, _ = gs.get_commands(env=env) + + assert "my_custom_cmd_a" in executables_set + assert "my_custom_cmd_b" in executables_set diff --git a/scripts/g.extension/tests/conftest.py b/scripts/g.extension/tests/conftest.py index 6fc0679c69e..7a18856f2b1 100644 --- a/scripts/g.extension/tests/conftest.py +++ b/scripts/g.extension/tests/conftest.py @@ -5,19 +5,15 @@ import pytest import grass.script as gs -from grass.tools import Tools # Using module-scoped fixture to avoid overhead of downloading addons repo. @pytest.fixture(scope="module") -def tools(tmp_path_factory): - """Tools with modified addon base directory (scope: module)""" +def session(tmp_path_factory): + """Session with modified addon base directory (scope: module)""" tmp_path = tmp_path_factory.mktemp("g_extension_tests") gs.create_project(tmp_path / "test") env = os.environ.copy() env["GRASS_ADDON_BASE"] = str(tmp_path / "addons") - with ( - gs.setup.init(tmp_path / "test", env=env) as session, - Tools(session=session, consistent_return_value=True) as tools, - ): - yield tools + with gs.setup.init(tmp_path / "test", env=env) as session: + yield session diff --git a/scripts/g.extension/tests/g_extension_test.py b/scripts/g.extension/tests/g_extension_test.py index c6fd946e92c..f0d4e5b292a 100644 --- a/scripts/g.extension/tests/g_extension_test.py +++ b/scripts/g.extension/tests/g_extension_test.py @@ -1,11 +1,18 @@ """Test g.extension""" import pytest +import grass.script as gs +from grass.tools import Tools # This should cover both C and Python tools. @pytest.mark.parametrize("name", ["r.stream.distance", "r.lake.series"]) -def test_install(tools, name): +def test_install(session, name): """Test that a tools installs and gives help message""" - tools.g_extension(extension=name) - assert tools.call_cmd([name, "--help"]).stderr + with Tools(session=session, consistent_return_value=True) as tools: + tools.g_extension(extension=name) + assert tools.call_cmd([name, "--help"]).stderr + # Check that the installed extension is in the get_commands() list + # i.e., GRASS_ADDON_BASE is accessible or not. + commands = gs.get_commands(env=session.env)[0] + assert name in commands, f"Extension {name} not found in get_commands() list"