Skip to content

Commit 14923ee

Browse files
authored
grass.app: Add mapset create subcommand (#6462)
For symmetry with project create, this adds a new mapset create subcommand. The mapset subcommand can be used, similarly to project, to group operations related to mapsets. Locking will be moved under mapset in #6437, so besides the availability of the subcommand for testing of other subcommands, the move of locking is the main motivation for adding the mapset create subcommand now. The mapset creation uses the semi-internal function grass.grassdb.create.create_mapset. The function parameters were adjusted to allow for a single path being provided (which was already supported through path resolution function, but not supported though the parameters). There are no parameters yet, and only basic creation and creation failure are handled (no computational region, overwrite, or search path). Tests cover creation and basic expectations of the new mapset, that is being separate from the default mapset, but part of the project. Example: python -m grass.app mapset create data/project/task_1
1 parent a3166cd commit 14923ee

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

python/grass/app/cli.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import grass.script as gs
2929
from grass.app.data import lock_mapset, unlock_mapset, MapsetLockingException
30+
from grass.grassdb.create import create_mapset
3031
from grass.exceptions import ScriptError
3132
from grass.tools import Tools
3233

@@ -91,6 +92,24 @@ def subcommand_create_project(args) -> int:
9192
return 0
9293

9394

95+
def add_mapset_subparser(subparsers):
96+
mapset_subparser = subparsers.add_parser("mapset", help="mapset related operations")
97+
mapset_subparsers = mapset_subparser.add_subparsers(dest="mapset_command")
98+
99+
subparser = mapset_subparsers.add_parser("create", help="create a new mapset")
100+
subparser.add_argument("path", help="path to the new mapset")
101+
subparser.set_defaults(func=subcommand_mapset_create)
102+
103+
104+
def subcommand_mapset_create(args) -> int:
105+
try:
106+
create_mapset(args.path)
107+
except (ScriptError, OSError) as error:
108+
print(_("Error creating mapset: {}").format(error), file=sys.stderr)
109+
return 1
110+
return 0
111+
112+
94113
def subcommand_lock_mapset(args):
95114
gs.setup.setup_runtime_env()
96115
try:
@@ -201,6 +220,7 @@ def main(args=None, program=None):
201220
run_subparser.set_defaults(func=subcommand_run_tool)
202221

203222
add_project_subparser(subparsers)
223+
add_mapset_subparser(subparsers)
204224

205225
subparser = subparsers.add_parser("lock", help="lock a mapset")
206226
subparser.add_argument("mapset_path", type=str)

python/grass/app/tests/grass_app_cli_test.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,99 @@ def test_subcommand_run_with_crs_as_pack_subprocess(pack_raster_file4x5_rows, ca
129129
assert json.loads(result.stdout)["srid"] == "EPSG:3358"
130130

131131

132+
def test_create_mapset(tmp_path):
133+
"""Check that we can create mapset and we can set its computational region"""
134+
project = tmp_path / "test_1"
135+
mapset = project / "data_1"
136+
assert main(["project", "create", str(project), "--crs", "EPSG:3358"]) == 0
137+
assert main(["mapset", "create", str(mapset)]) == 0
138+
assert mapset.exists()
139+
assert mapset.is_dir()
140+
rows = 13
141+
cols = 17
142+
assert (
143+
main(
144+
[
145+
"run",
146+
"--project",
147+
str(mapset),
148+
"g.region",
149+
f"rows={rows}",
150+
f"cols={cols}",
151+
]
152+
)
153+
== 0
154+
)
155+
result = subprocess.run(
156+
[
157+
sys.executable,
158+
"-m",
159+
"grass.app",
160+
"run",
161+
"--project",
162+
str(mapset),
163+
"g.region",
164+
"-p",
165+
"format=json",
166+
],
167+
capture_output=True,
168+
text=True,
169+
check=True,
170+
)
171+
region = json.loads(result.stdout)
172+
assert region["rows"] == rows
173+
assert region["cols"] == cols
174+
# Also check it is linked with the project.
175+
result = subprocess.run(
176+
[
177+
sys.executable,
178+
"-m",
179+
"grass.app",
180+
"run",
181+
"--project",
182+
str(mapset),
183+
"g.proj",
184+
"-p",
185+
"format=json",
186+
],
187+
capture_output=True,
188+
text=True,
189+
check=True,
190+
)
191+
assert json.loads(result.stdout)["srid"] == "EPSG:3358"
192+
# And check that we are really using the newly created mapset,
193+
# so the computational region in the default mapset is different.
194+
result = subprocess.run(
195+
[
196+
sys.executable,
197+
"-m",
198+
"grass.app",
199+
"run",
200+
"--project",
201+
str(project),
202+
"g.region",
203+
"-p",
204+
"format=json",
205+
],
206+
capture_output=True,
207+
text=True,
208+
check=True,
209+
)
210+
region = json.loads(result.stdout)
211+
assert region["rows"] == 1
212+
assert region["cols"] == 1
213+
214+
215+
def test_mapset_create_exists(tmp_path):
216+
"""Check that creating mapset fails when mapset already exists"""
217+
project = tmp_path / "test_1"
218+
mapset = project / "data_1"
219+
assert main(["project", "create", str(project)]) == 0
220+
assert main(["mapset", "create", str(mapset)]) == 0
221+
assert main(["mapset", "create", str(mapset)]) == 1
222+
# There is no overwrite option for mapset yet, so we don't test that.
223+
224+
132225
def test_create_overwrite(tmp_path):
133226
"""Check that creating when project exists fails unless overwrite is True"""
134227
project = tmp_path / "test_1"

python/grass/grassdb/create.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def _directory_to_mapset(path: MapsetPath):
103103
shutil.copy(region_path1, region_path2)
104104

105105

106-
def create_mapset(database, location, mapset):
106+
def create_mapset(database, location=None, mapset=None):
107107
"""Creates a mapset in a specified location"""
108108
path = resolve_mapset_path(
109109
database,

0 commit comments

Comments
 (0)