Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
d905882
grass.experimental: Add object to access modules as functions
wenzeslaus Apr 18, 2023
aaef183
Support verbosity, overwrite and region freezing
wenzeslaus Apr 21, 2023
54db575
Raise exception instead of calling handle_errors
wenzeslaus Apr 22, 2023
82f5894
Allow to specify stdin and use a new instance of Tools itself to exec…
wenzeslaus Apr 22, 2023
0f1e210
Add ignore errors, r_mapcalc example, draft tests
wenzeslaus Apr 22, 2023
f4e3fed
Add test for exceptions
wenzeslaus Apr 24, 2023
04087e8
Add tests and Makefile
wenzeslaus May 4, 2023
6ab8e40
Convert values to ints and floats in keyval
wenzeslaus May 4, 2023
744cfac
Do not overwrite by default to follow default behavior in GRASS GIS
wenzeslaus May 4, 2023
24c27e6
Add doc, remove old code and todos
wenzeslaus Jun 3, 2023
ff187a6
Add to top Makefile
wenzeslaus Jun 3, 2023
22773c8
Add docs for tests
wenzeslaus Jun 3, 2023
2911065
Allow test to fail because of the missing seed parameter (so results …
wenzeslaus Jun 4, 2023
3ac46c3
Merge branch 'main' into add-session-tools-object
echoix Nov 11, 2024
437d46e
Allow for optional output capture (error handling and printing still …
wenzeslaus Apr 23, 2025
cb8f483
Merge branch 'main' into add-session-tools-object
wenzeslaus Apr 23, 2025
a958142
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Apr 25, 2025
61972d4
Access JSON as dict directly without an attribute using getitem. Sugg…
wenzeslaus Apr 25, 2025
c86d8ff
Fix whitespace and regexp
wenzeslaus Apr 25, 2025
3b995c9
Represent not captured stdout as None, not empty string.
wenzeslaus Apr 25, 2025
d8c354d
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Apr 29, 2025
4cc5a32
Add run subcommand to have a CLI use case for the tools. It runs one …
wenzeslaus Apr 29, 2025
459b2ad
Update function name
wenzeslaus Apr 30, 2025
513c9f8
Add prototype code for numpy support
wenzeslaus Jun 2, 2025
24ef6b9
Merge main branch
wenzeslaus Jun 2, 2025
4a1e374
Make the special features standalone objects used by composition
wenzeslaus Jun 11, 2025
651df11
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 11, 2025
15aa936
Remove NumPy and pack file code
wenzeslaus Jun 11, 2025
5e9b50d
Capture the name of a subcommand to fix the tests
wenzeslaus Jun 11, 2025
2acdde0
Don't worry about specific r.univar output value for mean, just test …
wenzeslaus Jun 11, 2025
8f80eb9
Use the special grass.script sauce to run subprocess to have it worki…
wenzeslaus Jun 11, 2025
a422356
Use low level run functions internally, align result with subprocess.…
wenzeslaus Jun 12, 2025
8f1e8ff
Use tools API also for help in the CLI, support other special flags, …
wenzeslaus Jun 12, 2025
2085b94
Provide dir(tools) functionality
wenzeslaus Jun 12, 2025
d341183
Support prefixes in attribute access and error messages. Also improve…
wenzeslaus Jun 13, 2025
4f86be4
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 13, 2025
d8f6c40
Improve error message without tool suggestions (still include tool na…
wenzeslaus Jun 13, 2025
ac98322
Remove prefixes
wenzeslaus Jun 13, 2025
3abc34b
Clean up error handling, remove naive run_command family wrappers
wenzeslaus Jun 16, 2025
816b215
Add test with corresponding run_command family examples except feed, …
wenzeslaus Jun 17, 2025
e95bb51
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 17, 2025
3c99498
Use the no-copy approach for env taked also elsewhere like init which…
wenzeslaus Jun 17, 2025
14be050
Remove the feed_input_to method and stdin from the constructor. Inste…
wenzeslaus Jun 17, 2025
f9f7c0a
Add support for len on the result
wenzeslaus Jun 17, 2025
3a45c00
Make the file layout what it can be if not experimental, and make it …
wenzeslaus Jun 18, 2025
5658d3e
Disable Pylint warning because Pylint does not see the dynamic attrib…
wenzeslaus Jun 20, 2025
549cf1a
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 20, 2025
bbd80a5
Use create_project
wenzeslaus Jun 20, 2025
ff17612
Merge to update handle_errors
wenzeslaus Jun 24, 2025
7754592
Add doc for the main run function
wenzeslaus Jun 25, 2025
0587621
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 25, 2025
1345f79
Use input for stdin aligning with subprocess.run and Popen.communicat…
wenzeslaus Jun 25, 2025
11d7bb0
Use also command in result if kwargs are not available. Do not use se…
wenzeslaus Jun 25, 2025
35a785b
More migration examples. More examples with context managers.
wenzeslaus Jun 25, 2025
2176395
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 25, 2025
acff8ce
Add g.list examples
wenzeslaus Jun 25, 2025
caa2126
Fix typo in text comment
wenzeslaus Jun 25, 2025
8477243
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 26, 2025
94ea39c
Rely on grass.script.Popen defaults for text=True. Pass stderr as is …
wenzeslaus Jun 26, 2025
2bda54f
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 26, 2025
81ea7d3
Behave also like context manager (useful when used with other context…
wenzeslaus Jun 26, 2025
15fd4f7
Allow stderr to be captured even without capturing stdin
wenzeslaus Jun 27, 2025
2815511
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 27, 2025
46a43be
Update r.univar test
wenzeslaus Jun 27, 2025
7e10c91
Test result attributes and give more consistent results for JSON
wenzeslaus Jun 27, 2025
3352146
Remove r.pack-IO-related fixtures
wenzeslaus Jun 30, 2025
58162a8
Use possibly more common order for region and mask managers (both are…
wenzeslaus Jun 30, 2025
2c4d5dd
Document tests
wenzeslaus Jun 30, 2025
c098c16
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jun 30, 2025
54bdb4a
Sort tool suggestions, document tests
wenzeslaus Jul 1, 2025
b5de481
Document run and call functions
wenzeslaus Jul 1, 2025
91a775f
Add examples in doc which pass doctest and create repr for that
wenzeslaus Jul 1, 2025
a0eb515
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jul 1, 2025
a5601b3
Move tools from grass.experimental to grass.tools, but document them …
wenzeslaus Jul 2, 2025
505b72a
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jul 2, 2025
d31cdb4
Update the path in the Makefile
wenzeslaus Jul 4, 2025
603b20a
Update cmake build
wenzeslaus Jul 4, 2025
8cd22b3
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jul 4, 2025
5220b4a
Use grass.tools import in grass.app.cli
wenzeslaus Jul 6, 2025
660704d
Merge branch 'main' into add-session-tools-object
wenzeslaus Jul 17, 2025
39b500b
Merge branch 'main' into add-session-tools-object
wenzeslaus Jul 21, 2025
b5af2c0
Apply isort suggestions
wenzeslaus Jul 21, 2025
ddb4a7b
Add tests for specific values
wenzeslaus Jul 22, 2025
6b2b4fa
Fix copy-paste
wenzeslaus Jul 25, 2025
04ce72e
Make sure return code is passed from the tool subprocess, add tests
wenzeslaus Jul 25, 2025
f13cb23
Merge remote-tracking branch 'upstream/main' into add-session-tools-o…
wenzeslaus Jul 25, 2025
7e3514c
Test decoding and stripping of the result
wenzeslaus Jul 25, 2025
15967c4
No tool provided needs to be handled explicitly. Add missing smoke te…
wenzeslaus Jul 25, 2025
f091d64
Update python/grass/app/tests/grass_app_cli_test.py
echoix Jul 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion python/grass/app/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,30 @@
import tempfile
import os
import sys
import subprocess
from pathlib import Path


import grass.script as gs
from grass.app.data import lock_mapset, unlock_mapset, MapsetLockingException
from grass.experimental.tools import Tools


def subcommand_run_tool(args, tool_args: list, help: bool):
command = [args.tool_name, *tool_args]
with tempfile.TemporaryDirectory() as tmp_dir_name:
project_name = "project"
project_path = Path(tmp_dir_name) / project_name
gs.create_project(project_path)
with gs.setup.init(project_path) as session:
if help:
result = subprocess.run(command, env=session.env)
return result.returncode
tools = Tools(capture_output=False)
try:
tools.run_from_list(command)
except subprocess.CalledProcessError as error:
return error.returncode


def subcommand_lock_mapset(args):
Expand Down Expand Up @@ -77,6 +97,10 @@ def main(args=None, program=None):

# Subcommand parsers

subparser = subparsers.add_parser("run", help="run a tool")
subparser.add_argument("tool_name", type=str)
subparser.set_defaults(func=subcommand_run_tool)

subparser = subparsers.add_parser("lock", help="lock a mapset")
subparser.add_argument("mapset_path", type=str)
subparser.add_argument(
Expand Down Expand Up @@ -120,5 +144,27 @@ def main(args=None, program=None):
subparser.add_argument("page", type=str)
subparser.set_defaults(func=subcommand_show_man)

parsed_args = parser.parse_args(args)
# Parsing

if not args:
args = sys.argv[1:]
raw_args = args.copy()
add_back = None
if len(raw_args) > 2 and raw_args[0] == "run":
# Getting the --help of tools needs to work around the standard help mechanism
# of argparse.
# Maybe a better workaround is to use custom --help, action="help", print_help,
# and dedicated tool help function complimentary with g.manual subcommand
# interface.
if "--help" in raw_args[2:]:
raw_args.remove("--help")
add_back = "--help"
elif "--h" in raw_args[2:]:
raw_args.remove("--h")
add_back = "--h"
parsed_args, other_args = parser.parse_known_args(raw_args)
if parsed_args.subcommand == "run":
if add_back:
other_args.append(add_back)
return parsed_args.func(parsed_args, other_args, help=bool(add_back))
return parsed_args.func(parsed_args)
3 changes: 2 additions & 1 deletion python/grass/experimental/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ DSTDIR = $(ETC)/python/grass/experimental

MODULES = \
create \
mapset
mapset \
tools

PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
Expand Down
8 changes: 8 additions & 0 deletions python/grass/experimental/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ def xy_session_for_module(tmp_path_factory):
yield session


@pytest.fixture
def xy_dataset_session(tmp_path):
"""Creates a session with a mapset which has vector with a float column"""
gs.core._create_location_xy(tmp_path, "test") # pylint: disable=protected-access
with gs.setup.init(tmp_path / "test") as session:
yield session


@pytest.fixture
def unique_id():
"""A unique alphanumeric identifier"""
Expand Down
266 changes: 266 additions & 0 deletions python/grass/experimental/tests/grass_tools_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
"""Test grass.experimental.Tools class"""

import os
import json

import pytest


import grass.script as gs
from grass.experimental.mapset import TemporaryMapsetSession
from grass.experimental.tools import Tools
from grass.exceptions import CalledModuleError


def test_key_value_parser_number(xy_dataset_session):
"""Check that numbers are parsed as numbers"""
tools = Tools(session=xy_dataset_session)
assert tools.g_region(flags="g").keyval["nsres"] == 1


@pytest.mark.xfail
def test_key_value_parser_multiple_values(xy_dataset_session):
"""Check that strings and floats are parsed"""
tools = Tools(session=xy_dataset_session)
name = "surface"
tools.r_surf_gauss(output=name) # needs seed
result = tools.r_info(map=name, flags="g").keyval
assert result["datatype"] == "DCELL"
assert result["nsres"] == 1
result = tools.r_univar(map=name, flags="g").keyval
assert result["mean"] == pytest.approx(-0.756762744552762)


def test_json_parser(xy_dataset_session):
"""Check that JSON is parsed"""
tools = Tools(session=xy_dataset_session)
assert (
tools.g_search_modules(keyword="random", flags="j").json[0]["name"]
== "r.random"
)


def test_json_direct_access(xy_dataset_session):
"""Check that JSON is parsed"""
tools = Tools(session=xy_dataset_session)
assert tools.g_search_modules(keyword="random", flags="j")[0]["name"] == "r.random"


def test_json_direct_access_bad_key_type(xy_dataset_session):
"""Check that JSON is parsed"""
tools = Tools(session=xy_dataset_session)
with pytest.raises(TypeError):
tools.g_search_modules(keyword="random", flags="j")["name"]


def test_json_direct_access_bad_key_value(xy_dataset_session):
"""Check that JSON is parsed"""
tools = Tools(session=xy_dataset_session)
high_number = 100_000_000
with pytest.raises(IndexError):
tools.g_search_modules(keyword="random", flags="j")[high_number]


def test_json_direct_access_not_json(xy_dataset_session):
"""Check that JSON is parsed"""
tools = Tools(session=xy_dataset_session)
with pytest.raises(json.JSONDecodeError):
tools.g_search_modules(keyword="random")[0]["name"]


def test_stdout_as_text(xy_dataset_session):
"""Check that simple text is parsed and has no whitespace"""
tools = Tools(session=xy_dataset_session)
assert tools.g_mapset(flags="p").text == "PERMANENT"


def test_stdout_as_space_items(xy_dataset_session):
"""Check that whitespace-separated items are parsed"""
tools = Tools(session=xy_dataset_session)
assert tools.g_mapset(flags="l").space_items == ["PERMANENT"]


def test_stdout_split_whitespace(xy_dataset_session):
"""Check that whitespace-based split function works"""
tools = Tools(session=xy_dataset_session)
assert tools.g_mapset(flags="l").text_split() == ["PERMANENT"]


def test_stdout_split_space(xy_dataset_session):
"""Check that the split function works with space"""
tools = Tools(session=xy_dataset_session)
# Not a good example usage, but it tests the functionality.
assert tools.g_mapset(flags="l").text_split(" ") == ["PERMANENT", ""]


def test_stdout_without_capturing(xy_dataset_session):
"""Check that text is not present when not capturing it"""
tools = Tools(session=xy_dataset_session, capture_output=False)
assert not tools.g_mapset(flags="p").text
assert tools.g_mapset(flags="p").text is None


def test_direct_overwrite(xy_dataset_session):
"""Check overwrite as a parameter"""
tools = Tools(session=xy_dataset_session)
tools.r_random_surface(output="surface", seed=42)
tools.r_random_surface(output="surface", seed=42, overwrite=True)


def test_object_overwrite(xy_dataset_session):
"""Check overwrite as parameter of the tools object"""
tools = Tools(session=xy_dataset_session, overwrite=True)
tools.r_random_surface(output="surface", seed=42)
tools.r_random_surface(output="surface", seed=42)


def test_no_overwrite(xy_dataset_session):
"""Check that it fails without overwrite"""
tools = Tools(session=xy_dataset_session)
tools.r_random_surface(output="surface", seed=42)
with pytest.raises(CalledModuleError, match="overwrite"):
tools.r_random_surface(output="surface", seed=42)


def test_env_overwrite(xy_dataset_session):
"""Check that overwrite from env parameter is used"""
# env = xy_dataset_session.env.copy() # ideally
env = os.environ.copy() # for now
env["GRASS_OVERWRITE"] = "1"
tools = Tools(session=xy_dataset_session, env=env)
tools.r_random_surface(output="surface", seed=42)
tools.r_random_surface(output="surface", seed=42)


def test_global_overwrite_vs_env(xy_dataset_session):
"""Check that global overwrite is not used when separate env is used"""
# env = xy_dataset_session.env.copy() # ideally
env = os.environ.copy() # for now
os.environ["GRASS_OVERWRITE"] = "1" # change to xy_dataset_session.env
tools = Tools(session=xy_dataset_session, env=env)
tools.r_random_surface(output="surface", seed=42)
with pytest.raises(CalledModuleError, match="overwrite"):
tools.r_random_surface(output="surface", seed=42)
del os.environ["GRASS_OVERWRITE"] # check or ideally remove this


def test_global_overwrite_vs_init(xy_dataset_session):
"""Check that global overwrite is not used when separate env is used"""
tools = Tools(session=xy_dataset_session)
os.environ["GRASS_OVERWRITE"] = "1" # change to xy_dataset_session.env
tools.r_random_surface(output="surface", seed=42)
with pytest.raises(CalledModuleError, match="overwrite"):
tools.r_random_surface(output="surface", seed=42)
del os.environ["GRASS_OVERWRITE"] # check or ideally remove this


def test_stdin(xy_dataset_session):
"""Test that stdin is accepted"""
tools = Tools(session=xy_dataset_session)
tools.feed_input_to("13.45,29.96,200").v_in_ascii(
input="-", output="point", separator=","
)


def test_raises(xy_dataset_session):
"""Test that exception is raised for wrong parameter value"""
tools = Tools(session=xy_dataset_session)
wrong_name = "wrong_standard"
with pytest.raises(CalledModuleError, match=wrong_name):
tools.feed_input_to("13.45,29.96,200").v_in_ascii(

Check failure on line 170 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / macOS build

test_raises subprocess.CalledProcessError: Command '['v.in.ascii', 'input=-', 'output=point', 'format=wrong_standard', '--json']' returned non-zero exit status 1.

Check failure on line 170 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / pytest (ubuntu-22.04, 3.9)

test_raises subprocess.CalledProcessError: Command '['v.in.ascii', 'input=-', 'output=point', 'format=wrong_standard', '--json']' returned non-zero exit status 1.
input="-",
output="point",
format=wrong_name,
)


def test_run_command(xy_dataset_session):
"""Check run_command and its overwrite parameter"""
tools = Tools(session=xy_dataset_session)
tools.run_command("r.random.surface", output="surface", seed=42)
tools.run_command("r.random.surface", output="surface", seed=42, overwrite=True)


def test_parse_command_key_value(xy_dataset_session):
tools = Tools(session=xy_dataset_session)
assert tools.parse_command("g.region", flags="g")["nsres"] == "1"


def test_parse_command_json(xy_dataset_session):
tools = Tools(session=xy_dataset_session)
assert (
tools.parse_command("g.region", flags="g", format="json")["region"]["ns-res"]
== 1
)


def test_with_context_managers(tmpdir):
project = tmpdir / "project"
gs.create_project(project)
with gs.setup.init(project) as session:
tools = Tools(session=session)
tools.r_random_surface(output="surface", seed=42)
with TemporaryMapsetSession(env=tools.env) as mapset:
tools.r_random_surface(output="surface", seed=42, env=mapset.env)
with gs.MaskManager(env=mapset.env) as mask:
# TODO: Do actual test
tools.r_univar(map="surface", env=mask.env, format="json")[0]["mean"]

Check failure on line 207 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / macOS build

test_with_context_managers KeyError: 0

Check failure on line 207 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / pytest (ubuntu-22.04, 3.9)

test_with_context_managers KeyError: 0


def test_misspelling(xy_dataset_session):
tools = Tools(session=xy_dataset_session)
with pytest.raises(AttributeError, match=r"r\.slope\.aspect"):
tools.r_sloppy_respect()


def test_multiple_suggestions(xy_dataset_session):
tools = Tools(session=xy_dataset_session)
with pytest.raises(AttributeError, match=r"v\.db\.univar|db\.univar"):
tools.db_v_uni_var()


def test_tool_group_vs_model_name(xy_dataset_session):
tools = Tools(session=xy_dataset_session)
with pytest.raises(AttributeError, match=r"r\.sim\.water"):
tools.rSIMWEwater()


def test_wrong_attribute(xy_dataset_session):
tools = Tools(session=xy_dataset_session)
with pytest.raises(AttributeError, match="execute_big_command"):
tools.execute_big_command()

import numpy as np

Check failure on line 233 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / Python Code Quality Checks (ubuntu-22.04)

Ruff (E402)

python/grass/experimental/tests/grass_tools_test.py:233:1: E402 Module level import not at top of file

Check failure on line 233 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / Python Code Quality Checks (ubuntu-22.04)

Ruff (E305)

python/grass/experimental/tests/grass_tools_test.py:233:1: E305 Expected 2 blank lines after class or function definition, found (1)

def test_numpy_one_input(xy_dataset_session):

Check failure on line 235 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / Python Code Quality Checks (ubuntu-22.04)

Ruff (E302)

python/grass/experimental/tests/grass_tools_test.py:235:1: E302 Expected 2 blank lines, found 1
"""Check that global overwrite is not used when separate env is used"""
tools = Tools(session=xy_dataset_session)
tools.r_slope_aspect(elevation=np.ones((1, 1)), slope="slope")
assert tools.r_info(map="slope", format="json")["datatype"] == "FCELL"

# Other possible ways how to handle the syntax:

# class ToNumpy:
# pass

# class AsInput:
# pass

# def test_numpy_one_input(xy_dataset_session):
# """Check that global overwrite is not used when separate env is used"""
# tools = Tools(session=xy_dataset_session)
# tools.r_slope_aspect(elevation=np.ones((1, 1)), slope="slope", aspect="aspect", force_numpy_for_output=True)
# tools.r_slope_aspect(elevation=np.ones((1, 1)), slope=np.nulls(0,0), aspect="aspect")
# tools.r_slope_aspect(elevation=np.ones((1, 1)), slope=ToNumpy(), aspect="aspect")
# tools.r_slope_aspect(elevation=np.ones((1, 1)), slope=np.ndarray, aspect="aspect")
# tools.r_slope_aspect.ufunc(np.ones((1, 1)), slope=True, aspect=True, overwrite=True) # (np.array, np.array)
# tools.r_slope_aspect(elevation=np.ones((1, 1)), slope=AsInput, aspect=AsInput) # {"slope": np.array(...), "aspect": np.array(...) }
# assert tools.r_info(map="slope", format="json")["datatype"] == "FCELL"

def test_numpy_one_input_one_output(xy_dataset_session):

Check failure on line 260 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / Python Code Quality Checks (ubuntu-22.04)

Ruff (E302)

python/grass/experimental/tests/grass_tools_test.py:260:1: E302 Expected 2 blank lines, found 1
"""Check that global overwrite is not used when separate env is used"""
tools = Tools(session=xy_dataset_session)
tools.g_region(rows=2, cols=3)
slope = tools.r_slope_aspect(elevation=np.ones((2, 3)), slope=np.ndarray)
assert slope.shape == (2, 3)
assert slope[0] == 0

Check failure on line 266 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / macOS build

test_numpy_one_input_one_output ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Check failure on line 266 in python/grass/experimental/tests/grass_tools_test.py

View workflow job for this annotation

GitHub Actions / pytest (ubuntu-22.04, 3.9)

test_numpy_one_input_one_output ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Loading
Loading