-
-
Notifications
You must be signed in to change notification settings - Fork 368
grass.tools: Add API to access tools as functions #2923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 25 commits
d905882
aaef183
54db575
82f5894
0f1e210
f4e3fed
04087e8
6ab8e40
744cfac
24c27e6
ff187a6
22773c8
2911065
3ac46c3
437d46e
cb8f483
a958142
61972d4
c86d8ff
3b995c9
d8c354d
4cc5a32
459b2ad
513c9f8
24ef6b9
4a1e374
651df11
15aa936
5e9b50d
2acdde0
8f80eb9
a422356
8f1e8ff
2085b94
d341183
4f86be4
d8f6c40
ac98322
3abc34b
816b215
e95bb51
3c99498
14be050
f9f7c0a
3a45c00
5658d3e
549cf1a
bbd80a5
ff17612
7754592
0587621
1345f79
11d7bb0
35a785b
2176395
acff8ce
caa2126
8477243
94ea39c
2bda54f
81ea7d3
15fd4f7
2815511
46a43be
7e10c91
3352146
58162a8
2c4d5dd
c098c16
54bdb4a
b5de481
91a775f
a0eb515
a5601b3
505b72a
d31cdb4
603b20a
8cd22b3
5220b4a
660704d
39b500b
b5af2c0
ddb4a7b
6b2b4fa
04ce72e
f13cb23
7e3514c
15967c4
f091d64
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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
|
||
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
|
||
|
||
|
||
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
|
||
|
||
def test_numpy_one_input(xy_dataset_session): | ||
wenzeslaus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""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: | ||
wenzeslaus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# 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): | ||
wenzeslaus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""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
|
Uh oh!
There was an error while loading. Please reload this page.