Skip to content

Commit 8eb0a03

Browse files
authored
temporal: add parameter to skip creation of TGIS DB in current mapset on tgis.init (#7645)
* enable DB creation skip on tgis.init() * add test for tgis.init(skip_db_init=True)
1 parent 4542f71 commit 8eb0a03

2 files changed

Lines changed: 111 additions & 14 deletions

File tree

python/grass/temporal/core.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -543,14 +543,15 @@ def get_available_temporal_mapsets():
543543
###############################################################################
544544

545545

546-
def init(raise_fatal_error: bool = False, skip_db_version_check: bool = False):
547-
"""This function set the correct database backend from GRASS environmental
548-
variables and creates the grass temporal database structure for raster,
549-
vector and raster3d maps as well as for the space-time datasets strds,
550-
str3ds and stvds in case it does not exist.
546+
def init(
547+
raise_fatal_error: bool = False,
548+
skip_db_version_check: bool = False,
549+
skip_db_init: bool = False,
550+
):
551+
"""Initialize the temporal GIS system.
551552
552-
Several global variables are initiated and the messenger and C-library
553-
interface subprocesses are spawned.
553+
This function sets several global variables and spawns the messenger and
554+
C-library interface subprocesses.
554555
555556
Re-run this function in case the following GRASS variables change while
556557
the process runs:
@@ -572,7 +573,14 @@ def init(raise_fatal_error: bool = False, skip_db_version_check: bool = False):
572573
- GRASS_TGIS_PROFILE (True, False, 1, 0)
573574
- GRASS_TGIS_RAISE_ON_ERROR (True, False, 1, 0)
574575
575-
.. warning::
576+
If not otherwise requested (skip_db_init), this function will check for
577+
the existence of a temporal database and its version in the current mapset.
578+
If the database does not exist, it will be created, using the database
579+
backend from GRASS environment variables, with the GRASS temporal database
580+
structure for raster, vector and raster3d maps as well as for the space-time
581+
dataset types strds, str3ds and stvds.
582+
583+
.. warning::
576584
577585
This functions must be called before any spatio-temporal processing
578586
can be started
@@ -588,6 +596,14 @@ def init(raise_fatal_error: bool = False, skip_db_version_check: bool = False):
588596
database version check.
589597
Recommended to be used only for
590598
upgrade_temporal_database().
599+
:param skip_db_init: Set this True to allow init() to complete
600+
without initializing, (version) checking or creating
601+
a temporal database in the current mapset.
602+
Use this when the calling process only needs the
603+
global TGIS state (backend, mapset, interfaces)
604+
but does not require a temporal database in the
605+
current mapset for operations (like listing
606+
datasets, getting metainformation, ...).
591607
"""
592608
# We need to set the correct database backend and several global variables
593609
# from the GRASS mapset specific environment variables of g.gisenv and t.connect
@@ -600,9 +616,6 @@ def init(raise_fatal_error: bool = False, skip_db_version_check: bool = False):
600616

601617
raise_on_error = raise_fatal_error
602618

603-
# We must run t.connect at first to create the temporal database and to
604-
# get the environmental variables
605-
gs.run_command("t.connect", flags="c")
606619
grassenv = gs.gisenv()
607620

608621
new_mapset = grassenv["MAPSET"]
@@ -647,14 +660,11 @@ def init(raise_fatal_error: bool = False, skip_db_version_check: bool = False):
647660
# Start the C-library interface server
648661
_init_tgis_c_library_interface()
649662
msgr = get_tgis_message_interface()
650-
msgr.debug(1, "Initiate the temporal database")
651663

652664
msgr.debug(1, ("Raise on error id: %s" % str(raise_on_error)))
653665

654666
ciface = get_tgis_c_library_interface()
655667
current_mapset = decode(gs.gisenv().get("MAPSET"))
656-
driver_string = ciface.get_driver_name(current_mapset)
657-
database_string = ciface.get_database_name(current_mapset)
658668

659669
# Set the mapset check and the timestamp write
660670
if "TGIS_DISABLE_MAPSET_CHECK" in grassenv:
@@ -673,6 +683,17 @@ def init(raise_fatal_error: bool = False, skip_db_version_check: bool = False):
673683
enable_timestamp_write = False
674684
msgr.warning("TGIS_DISABLE_TIMESTAMP_WRITE is True")
675685

686+
if skip_db_init:
687+
return
688+
689+
msgr.debug(1, "Initiate the temporal database")
690+
# We must run t.connect at first to create the temporal database and to
691+
# get the environmental variables
692+
gs.run_command("t.connect", flags="c")
693+
694+
driver_string = ciface.get_driver_name(current_mapset)
695+
database_string = ciface.get_database_name(current_mapset)
696+
676697
if driver_string is not None and driver_string != "":
677698
driver_string = decode(driver_string)
678699
if driver_string == "sqlite":
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""Regression test for tgis.init() with and without TGIS DB initialization.
2+
3+
tgis.init() creates a TGIS database in the current mapset by default.
4+
For several tools that is not needed. This test checks if tgis.init()
5+
can be called with and without TGIS DB initialization and that the
6+
required files are created or not created accordingly.
7+
"""
8+
9+
import pytest
10+
11+
from pathlib import Path
12+
13+
import sqlite3
14+
15+
from grass.grassdb.create import create_mapset
16+
import grass.script as gs
17+
import grass.temporal as tgis
18+
19+
20+
@pytest.fixture
21+
def simple_mapset(tmp_path):
22+
"""Create a simple mapset and yield its path."""
23+
project_c = tmp_path / "c"
24+
gs.create_project(project_c)
25+
create_mapset(project_c / "c")
26+
return project_c / "c"
27+
28+
29+
def test_init_creates_tgis_db_if_not_skipped(simple_mapset):
30+
"""tgis.init() creates a DB and connection entry in VAR if not skipped."""
31+
project_c = simple_mapset
32+
var_file = Path(project_c) / "VAR"
33+
tgis_db = Path(project_c) / "tgis" / "sqlite.db"
34+
with gs.setup.init(project_c):
35+
tgis.init()
36+
ciface = tgis.get_tgis_c_library_interface()
37+
assert ciface.available_mapsets() == ["c", "PERMANENT"]
38+
assert tgis.get_tgis_version() == 2
39+
assert tgis.get_tgis_backend() == "sqlite"
40+
assert tgis.get_enable_mapset_check() is True
41+
assert tgis.get_enable_timestamp_write() is True
42+
assert tgis.get_sql_template_path().endswith("sql")
43+
# Test if the VAR file with the TGIS connection info is created
44+
assert var_file.exists()
45+
varfile_content = var_file.read_text(encoding="utf-8")
46+
assert "TGISDB_DRIVER" in varfile_content
47+
assert "TGISDB_DATABASE" in varfile_content
48+
# Test if the TGIS DB is created with content
49+
assert tgis_db.parent.exists()
50+
assert tgis_db.exists()
51+
assert (
52+
sqlite3.connect(tgis_db)
53+
.execute(
54+
"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%strds%';"
55+
)
56+
.fetchall()
57+
!= []
58+
)
59+
60+
61+
def test_init_succeeds_without_db_creation(simple_mapset):
62+
"""tgis.init(skip_db_init=True) does not create a DB or connection entry in VAR."""
63+
project_c = simple_mapset
64+
var_file = Path(project_c) / "VAR"
65+
tgis_db = Path(project_c) / "tgis"
66+
with gs.setup.init(project_c):
67+
tgis.init(skip_db_init=True)
68+
first_ciface = tgis.get_tgis_c_library_interface()
69+
assert first_ciface.available_mapsets() == ["c", "PERMANENT"]
70+
assert tgis.get_tgis_version() == 2
71+
assert tgis.get_tgis_backend() == "sqlite"
72+
assert tgis.get_enable_mapset_check() is True
73+
assert tgis.get_enable_timestamp_write() is True
74+
assert tgis.get_sql_template_path().endswith("sql")
75+
assert not var_file.exists()
76+
assert not tgis_db.exists()

0 commit comments

Comments
 (0)