From 763062856afe153375e5054821ee67dec4d1f727 Mon Sep 17 00:00:00 2001 From: khushjeet58 Date: Fri, 31 Jul 2026 10:36:37 +0530 Subject: [PATCH 1/2] r.out.xyz: add bottom-to-top output option --- scripts/r.out.xyz/r.out.xyz.py | 29 ++++++++++++++-- scripts/r.out.xyz/testsuite/test_r_out_xyz.py | 33 +++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/scripts/r.out.xyz/r.out.xyz.py b/scripts/r.out.xyz/r.out.xyz.py index 6df97f3c202..8273f6dd6bf 100755 --- a/scripts/r.out.xyz/r.out.xyz.py +++ b/scripts/r.out.xyz/r.out.xyz.py @@ -37,6 +37,10 @@ # % key: i # % description: Include no data values # %end +# %flag +# % key: b +# % description: Output rows from bottom to top +# %end import sys from grass.script import core as grass @@ -47,6 +51,7 @@ def main(): # if no output filename, output to stdout output = options["output"] donodata = flags["i"] + bottom_to_top = flags["b"] statsflags = "1g" if donodata else "1gn" parameters = { @@ -54,14 +59,34 @@ def main(): "input": options["input"], "separator": options["separator"], } - if output: + if output and not bottom_to_top: parameters.update(output=output) ret = 0 + try: - grass.run_command("r.stats", **parameters) + if bottom_to_top: + output_text = grass.read_command("r.stats", **parameters) + + lines = output_text.splitlines() + lines.reverse() + + if output_text.endswith("\n"): + output_text = "\n".join(lines) + "\n" + else: + output_text = "\n".join(lines) + + if output: + with open(output, "w", encoding="utf-8") as f: + f.write(output_text) + else: + print(output_text, end="") + else: + grass.run_command("r.stats", **parameters) + except CalledModuleError: ret = 1 + sys.exit(ret) diff --git a/scripts/r.out.xyz/testsuite/test_r_out_xyz.py b/scripts/r.out.xyz/testsuite/test_r_out_xyz.py index 615a410505f..75e1add64c9 100644 --- a/scripts/r.out.xyz/testsuite/test_r_out_xyz.py +++ b/scripts/r.out.xyz/testsuite/test_r_out_xyz.py @@ -27,6 +27,8 @@ def tearDownClass(cls): """Remove temporary region""" cls.del_temp_region() Path(cls.csvFile).unlink(missing_ok=True) + Path("normal.csv").unlink(missing_ok=True) + Path("bottom.csv").unlink(missing_ok=True) def test_r_out_xyz(self): """ASCII text file test""" @@ -37,6 +39,37 @@ def test_r_out_xyz(self): self.assertFileExists(filename=self.csvFile) + def test_r_out_xyz_bottom_to_top(self): + """Test bottom-to-top output ordering""" + + normal_file = "normal.csv" + bottom_file = "bottom.csv" + + module = SimpleModule( + "r.out.xyz", + input=self.mapName, + output=normal_file, + separator=",", + ) + self.assertModule(module) + + module = SimpleModule( + "r.out.xyz", + input=self.mapName, + output=bottom_file, + separator=",", + flags="b", + ) + self.assertModule(module) + + with open(normal_file, encoding="utf-8") as f: + normal_lines = f.read().splitlines() + + with open(bottom_file, encoding="utf-8") as f: + bottom_lines = f.read().splitlines() + + self.assertEqual(bottom_lines, list(reversed(normal_lines))) + if __name__ == "__main__": test() From 8ec4c9aef24b800f987a9b2fe8fccc218b93bb11 Mon Sep 17 00:00:00 2001 From: Khushjeet Singh Bhati Date: Fri, 2 Oct 2026 22:16:21 +0530 Subject: [PATCH 2/2] Update scripts/r.out.xyz/r.out.xyz.py Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- scripts/r.out.xyz/r.out.xyz.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/r.out.xyz/r.out.xyz.py b/scripts/r.out.xyz/r.out.xyz.py index 8273f6dd6bf..62f877c42da 100755 --- a/scripts/r.out.xyz/r.out.xyz.py +++ b/scripts/r.out.xyz/r.out.xyz.py @@ -77,8 +77,7 @@ def main(): output_text = "\n".join(lines) if output: - with open(output, "w", encoding="utf-8") as f: - f.write(output_text) + pathlib.Path(output).write_text(output_text, encoding="utf-8") else: print(output_text, end="") else: