From 5a42e6f25cc18d02ab5bf45259b7e0cf50370d9e Mon Sep 17 00:00:00 2001 From: saket0187 Date: Mon, 25 May 2026 15:33:09 +0530 Subject: [PATCH 1/4] Remove g.mapset and use gs.create_environment --- python/grass/temporal/stds_import.py | 40 +++++++++++++++------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/python/grass/temporal/stds_import.py b/python/grass/temporal/stds_import.py index 6c21dc18d5b..c3bcb740d48 100644 --- a/python/grass/temporal/stds_import.py +++ b/python/grass/temporal/stds_import.py @@ -344,6 +344,8 @@ def import_stds( # Create a new location based on the projection information and switch # into it old_env = gs.gisenv() + target_gisrc = None + old_gisrc = os.environ.get("GISRC") if location: try: proj4_string = Path(proj_file_name).read_text() @@ -359,16 +361,17 @@ def import_stds( _("Unable to create location %(l)s. Reason: %(e)s") % {"l": location, "e": str(e)} ) - # Switch to the new created location + # Create a temporary environment try: - gs.run_command( - "g.mapset", - mapset="PERMANENT", - project=location, - dbase=old_env["GISDBASE"], + target_gisrc, target_env = gs.create_environment( + old_env["GISDBASE"], location, "PERMANENT" + ) + os.environ["GISRC"] = target_gisrc + except OSError as e: + gs.fatal( + _("Unable to create environment for location %s. Reason: %s") + % (location, e) ) - except CalledModuleError: - gs.fatal(_("Unable to switch to location %s") % location) # create default database connection try: gs.run_command("t.connect", flags="d") @@ -598,19 +601,18 @@ def import_stds( update_cmd_list=False, ) - os.chdir(old_cwd) # Make sure the location is switched back correctly finally: + os.chdir(old_cwd) if location: - # Switch to the old location - try: - gs.run_command( - "g.mapset", - mapset=old_env["MAPSET"], - project=old_env["LOCATION_NAME"], - dbase=old_env["GISDBASE"], - ) - except CalledModuleError: - gs.warning(_("Switching to original location failed")) + # Restore the original session + if old_gisrc is not None: + os.environ["GISRC"] = old_gisrc + else: + os.environ.pop("GISRC", None) + + # Delete the temporary session file + if target_gisrc: + gs.try_remove(target_gisrc) gs.set_raise_on_error(old_state) From e9d4189cfeee9a588d83e402c1dfcdb2b03b52f5 Mon Sep 17 00:00:00 2001 From: saket0187 Date: Tue, 2 Jun 2026 15:22:13 +0530 Subject: [PATCH 2/4] Fixed test file --- .../testsuite/test_temporal_rast_import.py | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/temporal/t.rast.import/testsuite/test_temporal_rast_import.py b/temporal/t.rast.import/testsuite/test_temporal_rast_import.py index 4a0decbf82d..1df553fa6e2 100644 --- a/temporal/t.rast.import/testsuite/test_temporal_rast_import.py +++ b/temporal/t.rast.import/testsuite/test_temporal_rast_import.py @@ -19,13 +19,17 @@ class TestRasterImport(TestCase): @classmethod def tearDownClass(cls): - """Remove the temporary region""" - cls.del_temp_region() + """Remove the imported data""" cls.runModule("t.remove", flags="df", inputs="A") def test_import(self): self.assertModule( - "t.rast.import", input=self.input_, output="A", basename="a", overwrite=True + "t.rast.import", + flags="o", + input=self.input_, + output="A", + basename="a", + overwrite=True, ) tinfo = """start_time='2000-01-01 00:00:00' end_time='2001-01-01 00:00:00' @@ -34,8 +38,14 @@ def test_import(self): north=320000.0 south=10000.0 east=935000.0 - west=120000.0 - """ + west=120000.0""" - info = SimpleModule("t.info", flags="g", input="A") - self.assertModuleKeyValue(module=info, reference=tinfo, precision=2, sep="=") + self.assertModuleKeyValue( + module="t.info", input="A", flags="g", reference=tinfo, precision=2, sep="=" + ) + + +if __name__ == "__main__": + from grass.gunittest.main import test + + test() From a7f1ade301837bbae930a2b9c2c2cbd28c7a4b65 Mon Sep 17 00:00:00 2001 From: saket0187 Date: Mon, 8 Jun 2026 15:49:56 +0530 Subject: [PATCH 3/4] Add test and fix --- python/grass/temporal/stds_import.py | 18 +++++++++++++++ temporal/t.rast.import/t.rast.import.py | 2 +- .../testsuite/test_temporal_rast_import.py | 23 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/python/grass/temporal/stds_import.py b/python/grass/temporal/stds_import.py index c3bcb740d48..6e7e900101d 100644 --- a/python/grass/temporal/stds_import.py +++ b/python/grass/temporal/stds_import.py @@ -47,6 +47,7 @@ import grass.script as gs from grass.exceptions import CalledModuleError +from grass.temporal import core as tcore from .core import get_current_mapset, get_tgis_message_interface from .factory import dataset_factory @@ -367,6 +368,16 @@ def import_stds( old_env["GISDBASE"], location, "PERMANENT" ) os.environ["GISRC"] = target_gisrc + + # The temporal framework uses background C-subprocesses that cache the + # original environment. We must stop them and clear the globals so + # they are forced to restart and connect to the new project. + tcore.stop_subprocesses() + tcore.message_interface = None + tcore.c_library_interface = None + tcore.tgis_backend = None + tcore.tgis_database_string = None + except OSError as e: gs.fatal( _("Unable to create environment for location %s. Reason: %s") @@ -611,6 +622,13 @@ def import_stds( else: os.environ.pop("GISRC", None) + # Stop the subprocesses running in the temporary project. + tcore.stop_subprocesses() + tcore.message_interface = None + tcore.c_library_interface = None + tcore.tgis_backend = None + tcore.tgis_database_string = None + # Delete the temporary session file if target_gisrc: gs.try_remove(target_gisrc) diff --git a/temporal/t.rast.import/t.rast.import.py b/temporal/t.rast.import/t.rast.import.py index 7c176eff571..6c113cec784 100755 --- a/temporal/t.rast.import/t.rast.import.py +++ b/temporal/t.rast.import/t.rast.import.py @@ -69,7 +69,7 @@ # %option # % key: project # % type: string -# % description: Create a new project and import the data into it. Do not run this module in parallel or interrupt it when a new project should be created +# % description: Create a new project and import the data into it. # % required: no # % multiple: no # %end diff --git a/temporal/t.rast.import/testsuite/test_temporal_rast_import.py b/temporal/t.rast.import/testsuite/test_temporal_rast_import.py index 1df553fa6e2..3c1ddf83fc0 100644 --- a/temporal/t.rast.import/testsuite/test_temporal_rast_import.py +++ b/temporal/t.rast.import/testsuite/test_temporal_rast_import.py @@ -10,12 +10,16 @@ """ import os +import pathlib +import shutil +import grass.script as gs from grass.gunittest.case import TestCase class TestRasterImport(TestCase): input_ = os.path.join("data", "precip_2000.tar.bzip2") + new_project_name = "test_project_import" @classmethod def tearDownClass(cls): @@ -44,6 +48,25 @@ def test_import(self): module="t.info", input="A", flags="g", reference=tinfo, precision=2, sep="=" ) + def test_import_new_project(self): + """Test the project option.""" + path = os.path.join(gs.gisenv()["GISDBASE"], self.new_project_name) + + shutil.rmtree(path, ignore_errors=True) + self.addCleanup(shutil.rmtree, path, ignore_errors=True) + + self.assertModule( + "t.rast.import", + flags="o", + input=self.input_, + output="B", + basename="b", + project=self.new_project_name, + overwrite=True, + ) + + self.assertTrue(pathlib.Path(path).exists()) + if __name__ == "__main__": from grass.gunittest.main import test From bc59b077864bae191d33ca4286d00ba51500a865 Mon Sep 17 00:00:00 2001 From: saket0187 Date: Tue, 9 Jun 2026 13:52:55 +0530 Subject: [PATCH 4/4] Add gisenv() checks --- python/grass/temporal/stds_import.py | 19 +++---------------- .../testsuite/test_temporal_rast_import.py | 2 ++ 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/python/grass/temporal/stds_import.py b/python/grass/temporal/stds_import.py index 6e7e900101d..c8aed5f9215 100644 --- a/python/grass/temporal/stds_import.py +++ b/python/grass/temporal/stds_import.py @@ -47,7 +47,6 @@ import grass.script as gs from grass.exceptions import CalledModuleError -from grass.temporal import core as tcore from .core import get_current_mapset, get_tgis_message_interface from .factory import dataset_factory @@ -369,15 +368,6 @@ def import_stds( ) os.environ["GISRC"] = target_gisrc - # The temporal framework uses background C-subprocesses that cache the - # original environment. We must stop them and clear the globals so - # they are forced to restart and connect to the new project. - tcore.stop_subprocesses() - tcore.message_interface = None - tcore.c_library_interface = None - tcore.tgis_backend = None - tcore.tgis_database_string = None - except OSError as e: gs.fatal( _("Unable to create environment for location %s. Reason: %s") @@ -622,12 +612,9 @@ def import_stds( else: os.environ.pop("GISRC", None) - # Stop the subprocesses running in the temporary project. - tcore.stop_subprocesses() - tcore.message_interface = None - tcore.c_library_interface = None - tcore.tgis_backend = None - tcore.tgis_database_string = None + from .core import init + + init() # Delete the temporary session file if target_gisrc: diff --git a/temporal/t.rast.import/testsuite/test_temporal_rast_import.py b/temporal/t.rast.import/testsuite/test_temporal_rast_import.py index 3c1ddf83fc0..8f16a1cdc3c 100644 --- a/temporal/t.rast.import/testsuite/test_temporal_rast_import.py +++ b/temporal/t.rast.import/testsuite/test_temporal_rast_import.py @@ -51,6 +51,7 @@ def test_import(self): def test_import_new_project(self): """Test the project option.""" path = os.path.join(gs.gisenv()["GISDBASE"], self.new_project_name) + original_env = gs.gisenv() shutil.rmtree(path, ignore_errors=True) self.addCleanup(shutil.rmtree, path, ignore_errors=True) @@ -66,6 +67,7 @@ def test_import_new_project(self): ) self.assertTrue(pathlib.Path(path).exists()) + self.assertDictEqual(original_env, gs.gisenv()) if __name__ == "__main__":