-
-
Notifications
You must be signed in to change notification settings - Fork 283
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
grass.script: Resolve path to mapset in setup.init (#1829)
This replaces the db/loc/mapset defaults in grass.script.setup.init which were for demolocation by more useful behavior: Basic case is passing all three values as before, but when gisdbase and location are provided and mapset is not PERMANENT is used. This is actually also the same as before, but now it fails if location is not provided. Additionally, location and mapset parameters can be left out if the gisdbase (aka path) parameter points to the mapset or location. In that case, additional check is done to resolve to see if it is a valid mapset if not, PERMANENT is used instead. If there is no PERMANENT, the path is left as is. The grass.jupyter.init uses grass.script.setup.init, so these changes apply there, too. The gisbase is now automatically detected if possible, but also customizable with new convenient options (see doc). No more gisbase and gisdbase. Renamed to grass_path and path, respectively. Parameters are also reordered. This will break existing code, but for 7 to 8 switch that's okay. A possibly breaking change of behavior is that the init function checks for validity of the mapset and raises an exception if the mapset is invalid (does not exist or fails validity test from grass.grassdb). Most of the original code from grass.script.setup.init is now in a separate function which sets up the runtime environment (env vars for libs etc.), but does not do anything with the data (or session file/gisrc). grass.grassdb now has a new MapsetPath class to simplify path operations around mapset and especially switching between db/loc/mapset and full path to mapset. New function resolve_mapset_path takes care of the path or db/loc/mapset to actual mapset conversion. MapsetPath is reusable and os.PathLike. GIS_LOCK is moved in the code as it is a part of mapset/data session, not runtime. Update the basic example notebook for the new API (no gisbase passed, full path to mapset is enough) and correct usage of the old one (no reference to rcfile, finish call added). Use Path in split_mapset_path and use that in resolve_mapset_path. Use Path.cwd() / path on Windows if the path does not exist.
- Loading branch information
1 parent
c84312a
commit ffb79ae
Showing
5 changed files
with
487 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
# MODULE: Test of grass.grassdb.manage | ||
# | ||
# AUTHOR(S): Vaclav Petras <wenzeslaus gmail com> | ||
# | ||
# PURPOSE: Test of managing the GRASS database/location/mapset structure | ||
# | ||
# COPYRIGHT: (C) 2021 Vaclav Petras, and by the GRASS Development Team | ||
# | ||
# This program is free software under the GNU General Public | ||
# License (>=v2). Read the file COPYING that comes with GRASS | ||
# for details. | ||
|
||
"""Tests of grass.grassdb.manage""" | ||
|
||
from pathlib import Path | ||
|
||
from grass.grassdb.manage import MapsetPath, resolve_mapset_path, split_mapset_path | ||
from grass.gunittest.case import TestCase | ||
from grass.gunittest.gmodules import call_module | ||
from grass.gunittest.main import test | ||
|
||
|
||
class TestMapsetPath(TestCase): | ||
"""Check that object can be constructed""" | ||
|
||
def test_mapset_from_path_object(self): | ||
"""Check that path is correctly stored""" | ||
path = "does/not/exist/" | ||
location_name = "test_location_A" | ||
mapset_name = "test_mapset_1" | ||
full_path = Path(path) / location_name / mapset_name | ||
mapset_path = MapsetPath( | ||
path=full_path, directory=path, location=location_name, mapset=mapset_name | ||
) | ||
# Paths are currently stored as is (not resolved). | ||
self.assertEqual(mapset_path.directory, path) | ||
self.assertEqual(mapset_path.location, location_name) | ||
self.assertEqual(mapset_path.mapset, mapset_name) | ||
self.assertEqual(mapset_path.path, Path(path) / location_name / mapset_name) | ||
|
||
def test_mapset_from_str(self): | ||
"""Check with path from str and database directory as Path""" | ||
path = "does/not/exist" | ||
location_name = "test_location_A" | ||
mapset_name = "test_mapset_1" | ||
full_path = Path(path) / location_name / mapset_name | ||
mapset_path = MapsetPath( | ||
path=str(full_path), | ||
directory=Path(path), | ||
location=location_name, | ||
mapset=mapset_name, | ||
) | ||
# Paths are currently stored as is (not resolved). | ||
self.assertEqual(mapset_path.directory, path) | ||
self.assertEqual(mapset_path.location, location_name) | ||
self.assertEqual(mapset_path.mapset, mapset_name) | ||
self.assertEqual(mapset_path.path, Path(path) / location_name / mapset_name) | ||
|
||
|
||
class TestSplitMapsetPath(TestCase): | ||
"""Check that split works with different parameters""" | ||
|
||
def test_split_path(self): | ||
"""Check that pathlib.Path is correctly split""" | ||
ref_db = "does/not/exist" | ||
ref_location = "test_location_A" | ||
ref_mapset = "test_mapset_1" | ||
path = Path(ref_db) / ref_location / ref_mapset | ||
new_db, new_location, new_mapset = split_mapset_path(path) | ||
self.assertEqual(new_db, ref_db) | ||
self.assertEqual(new_location, ref_location) | ||
self.assertEqual(new_mapset, ref_mapset) | ||
|
||
def test_split_str(self): | ||
"""Check that path as str is correctly split""" | ||
ref_db = "does/not/exist" | ||
ref_location = "test_location_A" | ||
ref_mapset = "test_mapset_1" | ||
path = Path(ref_db) / ref_location / ref_mapset | ||
new_db, new_location, new_mapset = split_mapset_path(str(path)) | ||
self.assertEqual(new_db, ref_db) | ||
self.assertEqual(new_location, ref_location) | ||
self.assertEqual(new_mapset, ref_mapset) | ||
|
||
def test_split_str_trailing_slash(self): | ||
"""Check that path as str with a trailing slash is correctly split""" | ||
ref_db = "does/not/exist" | ||
ref_location = "test_location_A" | ||
ref_mapset = "test_mapset_1" | ||
path = Path(ref_db) / ref_location / ref_mapset | ||
new_db, new_location, new_mapset = split_mapset_path(str(path) + "/") | ||
self.assertEqual(new_db, ref_db) | ||
self.assertEqual(new_location, ref_location) | ||
self.assertEqual(new_mapset, ref_mapset) | ||
|
||
|
||
class TestResolveMapsetPath(TestCase): | ||
"""Check expected results for current mapset and for a non-existent one""" | ||
|
||
def test_default_mapset_exists(self): | ||
"""Check that default mapset is found for real path/location. | ||
The location (or mapset) may not exist, but exist in the test. | ||
""" | ||
db_path = call_module("g.gisenv", get="GISDBASE").strip() | ||
loc_name = call_module("g.gisenv", get="LOCATION_NAME").strip() | ||
mapset_path = resolve_mapset_path(path=db_path, location=loc_name) | ||
self.assertEqual(mapset_path.mapset, "PERMANENT") | ||
|
||
def test_default_mapset_does_not_exist(self): | ||
"""Check that default mapset is found for non-existent path/location. | ||
The location (or mapset) do not exist. | ||
""" | ||
mapset_path = resolve_mapset_path( | ||
path="does/not/exist", location="does_not_exit" | ||
) | ||
self.assertEqual(mapset_path.mapset, "PERMANENT") | ||
|
||
def test_default_mapset_with_path(self): | ||
"""Check that default mapset is found for path. | ||
This requires the location (with default mapset) to exists. | ||
""" | ||
db_path = call_module("g.gisenv", get="GISDBASE").strip() | ||
loc_name = call_module("g.gisenv", get="LOCATION_NAME").strip() | ||
mapset_path = resolve_mapset_path(path=Path(db_path) / loc_name) | ||
self.assertEqual(mapset_path.mapset, "PERMANENT") | ||
|
||
def test_mapset_from_parts(self): | ||
"""Check that a non-existing path is correctly constructed.""" | ||
path = "does/not/exist" | ||
location_name = "test_location_A" | ||
mapset_name = "test_mapset_1" | ||
mapset_path = resolve_mapset_path( | ||
path=path, location=location_name, mapset=mapset_name | ||
) | ||
self.assertEqual(mapset_path.directory, str(Path(path).resolve())) | ||
self.assertEqual(mapset_path.location, location_name) | ||
self.assertEqual(mapset_path.mapset, mapset_name) | ||
self.assertEqual( | ||
mapset_path.path, Path(path).resolve() / location_name / mapset_name | ||
) | ||
|
||
def test_mapset_from_path(self): | ||
"""Check that a non-existing path is correctly parsed.""" | ||
path = "does/not/exist/" | ||
location_name = "test_location_A" | ||
mapset_name = "test_mapset_1" | ||
full_path = str(Path(path) / location_name / mapset_name) | ||
mapset_path = resolve_mapset_path(path=full_path) | ||
self.assertEqual(mapset_path.directory, str(Path(path).resolve())) | ||
self.assertEqual(mapset_path.location, location_name) | ||
self.assertEqual(mapset_path.mapset, mapset_name) | ||
self.assertEqual( | ||
mapset_path.path, Path(path).resolve() / location_name / mapset_name | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
test() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.