Skip to content

Commit

Permalink
grass.script: Reduce use of env in create_location (#3428)
Browse files Browse the repository at this point in the history
* Reduces use of runtime environment in the create_location function (gisenv call removed).
* Reduces scope of gisrc which simplifies cleanup.
* Adds 4 tests for basic creation of the location (project).
  • Loading branch information
wenzeslaus committed Feb 16, 2024
1 parent 3f03909 commit 7df156f
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 6 deletions.
11 changes: 5 additions & 6 deletions python/grass/script/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1714,16 +1714,11 @@ def create_location(
# create dbase if not exists
if not os.path.exists(dbase):
os.mkdir(dbase)
if epsg or proj4 or filename or wkt:
# here the location shouldn't really matter
tmp_gisrc, env = create_environment(
dbase, gisenv()["LOCATION_NAME"], "PERMANENT"
)

# check if location already exists
if os.path.exists(os.path.join(dbase, location)):
if not overwrite:
warning(_("Location <%s> already exists. Operation canceled.") % location)
try_remove(tmp_gisrc)
return
else:
warning(
Expand All @@ -1738,6 +1733,10 @@ def create_location(
if datum_trans:
kwargs["datum_trans"] = datum_trans

if epsg or proj4 or filename or wkt:
# The names don't really matter here.
tmp_gisrc, env = create_environment(dbase, "<placeholder>", "<placeholder>")

if epsg:
ps = pipe_command(
"g.proj",
Expand Down
103 changes: 103 additions & 0 deletions python/grass/script/tests/grass_script_core_location_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""Test functions in grass.script.setup"""

import multiprocessing

import grass.script as gs


# All init tests change the global environment, but when it really matters,
# we use a separate process.
# Ideally, the functions would support env parameter and the test
# would mostly use that.
def run_in_subprocess(function):
"""Run function in a separate process
The function must take a Queue and put its result there.
The result is then returned from this function.
"""
queue = multiprocessing.Queue()
process = multiprocessing.Process(target=function, args=(queue,))
process.start()
result = queue.get()
process.join()
return result


def create_and_get_srid(tmp_path):
"""Create location on the same path as the current one"""
bootstrap_location = "bootstrap"
desired_location = "desired"
gs.core._create_location_xy(
tmp_path, bootstrap_location
) # pylint: disable=protected-access
with gs.setup.init(tmp_path / bootstrap_location):
gs.create_location(tmp_path, desired_location, epsg="3358")
assert (tmp_path / desired_location).exists()
wkt_file = tmp_path / desired_location / "PERMANENT" / "PROJ_WKT"
assert wkt_file.exists()
gs.run_command("g.gisenv", set=f"GISDBASE={tmp_path}")
gs.run_command("g.gisenv", set=f"LOCATION_NAME={desired_location}")
gs.run_command("g.gisenv", set="MAPSET=PERMANENT")
return gs.parse_command("g.proj", flags="g")["srid"]


def test_with_same_path(tmp_path):
"""Check correct EPSG is created with same path as the current one"""
srid = create_and_get_srid(tmp_path)
assert srid == "EPSG:3358"


def test_with_init_in_subprocess(tmp_path):
"""Check creation when running in a subprocess"""

def workload(queue):
"""Transfer the return value using queue"""
queue.put(create_and_get_srid(tmp_path))

epsg = run_in_subprocess(workload)
assert epsg == "EPSG:3358"


def test_with_different_path(tmp_path):
"""Check correct EPSG is created with different path"""
bootstrap_location = "bootstrap"
desired_location = "desired"
tmp_path_a = tmp_path / "a"
tmp_path_b = tmp_path / "b"
tmp_path_a.mkdir()
gs.core._create_location_xy(
tmp_path_a, bootstrap_location
) # pylint: disable=protected-access
with gs.setup.init(tmp_path_a / bootstrap_location):
gs.create_location(tmp_path_b, desired_location, epsg="3358")
assert (tmp_path_b / desired_location).exists()
wkt_file = tmp_path_b / desired_location / "PERMANENT" / "PROJ_WKT"
assert wkt_file.exists()
gs.run_command("g.gisenv", set=f"GISDBASE={tmp_path_b}")
gs.run_command("g.gisenv", set=f"LOCATION_NAME={desired_location}")
gs.run_command("g.gisenv", set="MAPSET=PERMANENT")
epsg = gs.parse_command("g.proj", flags="g")["srid"]
assert epsg == "EPSG:3358"


def test_files(tmp_path):
"""Check expected files are created"""
bootstrap_location = "bootstrap"
desired_location = "desired"
gs.core._create_location_xy(
tmp_path, bootstrap_location
) # pylint: disable=protected-access
with gs.setup.init(tmp_path / bootstrap_location):
description = "This is a test (not Gauss-Krüger or Křovák)"
gs.create_location(tmp_path, desired_location, epsg="3358", desc=description)
assert (tmp_path / desired_location).exists()
base_path = tmp_path / desired_location / "PERMANENT"
assert (base_path / "PROJ_WKT").exists()
assert (base_path / "PROJ_SRID").exists()
assert (base_path / "PROJ_UNITS").exists()
assert (base_path / "PROJ_INFO").exists()
assert (base_path / "DEFAULT_WIND").exists()
assert (base_path / "WIND").exists()
description_file = base_path / "MYNAME"
assert description_file.exists()
assert description_file.read_text(encoding="utf-8").strip() == description

0 comments on commit 7df156f

Please sign in to comment.