diff --git a/python/grass/script/tests/utils_test.py b/python/grass/script/tests/utils_test.py index 7289161173b..c2d703b1960 100644 --- a/python/grass/script/tests/utils_test.py +++ b/python/grass/script/tests/utils_test.py @@ -26,6 +26,32 @@ def test_unrecognized_separator(): assert gs.separator("apple") == "apple" +@pytest.mark.parametrize( + ("dms", "expected"), + [ + ("26:45:30", 26.758333333333333), + ("+26:45:30", 26.758333333333333), + ("-26:45:30", -26.758333333333333), + ("26:45:30N", 26.758333333333333), + ("26:45:30E", 26.758333333333333), + ("26:45:30S", -26.758333333333333), + ("26:45:30W", -26.758333333333333), + ("-0:30:0", -0.5), + ("12.5", 12.5), + ("-12.5", -12.5), + ], +) +def test_float_or_dms(dms, expected): + """Check that sign and hemisphere letters are applied to the whole value""" + assert gs.float_or_dms(dms) == pytest.approx(expected) + + +def test_float_or_dms_empty(): + """Check that an empty string is reported as an invalid value""" + with pytest.raises(ValueError, match="could not convert"): + gs.float_or_dms("") + + def test_KeyValue_keys(): """Check that KeyValue class works like a Dict""" kv = gs.KeyValue() diff --git a/python/grass/script/utils.py b/python/grass/script/utils.py index c9e915a0de6..ab627b1f504 100644 --- a/python/grass/script/utils.py +++ b/python/grass/script/utils.py @@ -50,13 +50,26 @@ def float_or_dms(s) -> float: >>> round(float_or_dms("26:0:0.1"), 5) 26.00003 + A leading minus sign or a trailing S or W hemisphere letter + makes the result negative: + + >>> round(float_or_dms("-26:45:30"), 5) + -26.75833 + >>> round(float_or_dms("26:45:30S"), 5) + -26.75833 + :param s: DMS value :return: float value """ - if s[-1] in {"E", "W", "N", "S"}: + negative = s[-1:] in {"S", "W"} + if s[-1:] in {"E", "W", "N", "S"}: s = s[:-1] - return sum(float(x) / 60**n for (n, x) in enumerate(s.split(":"))) + if s[:1] in {"-", "+"}: + negative = negative or s[0] == "-" + s = s[1:] + value = sum(float(x) / 60**n for (n, x) in enumerate(s.split(":"))) + return -value if negative else value def separator(sep: str) -> str: diff --git a/scripts/r.import/r.import.py b/scripts/r.import/r.import.py index 8177d371fbb..1da33bdc98f 100644 --- a/scripts/r.import/r.import.py +++ b/scripts/r.import/r.import.py @@ -353,18 +353,10 @@ def main(): w = srcregion["w"] except ValueError: # import into latlong, expect 53:39:06.894826N srcregion = gs.parse_key_val(tgtextents, vsep=" ") - n = gs.float_or_dms(srcregion["n"][:-1]) * ( - -1 if srcregion["n"][-1] == "S" else 1 - ) - s = gs.float_or_dms(srcregion["s"][:-1]) * ( - -1 if srcregion["s"][-1] == "S" else 1 - ) - e = gs.float_or_dms(srcregion["e"][:-1]) * ( - -1 if srcregion["e"][-1] == "W" else 1 - ) - w = gs.float_or_dms(srcregion["w"][:-1]) * ( - -1 if srcregion["w"][-1] == "W" else 1 - ) + n = gs.float_or_dms(srcregion["n"]) + s = gs.float_or_dms(srcregion["s"]) + e = gs.float_or_dms(srcregion["e"]) + w = gs.float_or_dms(srcregion["w"]) env["GRASS_REGION"] = gs.region_env(n=n, s=s, e=e, w=w)