Opened 5 years ago

Last modified 4 years ago

#3845 new defect

pygrass + mapset resolution

Reported by: pmav99 Owned by: grass-dev@…
Priority: normal Milestone: 7.8.3
Component: PyGRASS Version: svn-trunk
Keywords: Cc:
CPU: Unspecified Platform: Unspecified

Description

I am not sure if this is a bug or just lack of understanding from my part.

The following function:

  1. Creates a new (temporary) mapset (e.g. named A)
  2. Makes A the current mapset
  3. Creates a map inside A
  4. Confirms that the map exists
  5. Tries to open the map using RasterRow
  6. On exit, restores PERMANENT as the current mapset and deletes A

You may call this function as many times as you want and it will work as long as you use the same mapset name. As soon as you change the mapset name though it will fail with the rather confusing exception:

grass.exceptions.OpenError: The map does not exist, I can't open in 'r' mode

Note: The function has confirmed that the map exists before the exception

This is the code:

import grass.script as gscript
import grass.pygrass as pygrass
import grass.pygrass.raster
import grass.pygrass.gis

# import grass.lib.gis as libgis
# libgis.G_gisinit("asdf")

gscript.run_command("g.region", n=10, s=0, e=10, w=0, res=1)

def test(mapset_name, map_name):
    # create a new mapset and make it the current one
    pygrass.gis.make_mapset(mapset_name)
    pygrass.gis.set_current_mapset(mapset_name)

    # Create a map inside the new mapset and try to open it using pygrass methods
    try:
        mapset = pygrass.gis.Mapset(mapset_name)
        assert mapset.glist("raster") == []
        gscript.run_command("r.mapcalc", expression=f"{map_name}=1", quiet=True)
        assert mapset.glist("raster") == [map_name]
        # OK we've proved that the map exists and that the mapset object can see it
        # Let's now try to open the map though. As we will see, opening the map will fail
        r = pygrass.raster.RasterRow(map_name)
        r.open()                                        # you will get an exception here
        assert r.is_open()
    finally:
        # cleanup
        pygrass.gis.set_current_mapset("PERMANENT")
        mapset.delete()


# (Re-)create and delete the "aaa" mapset as many times as you want.
# Everything will be working just fine.
test("aaa", "m1")
test("aaa", "m1")
test("aaa", "m1")
test("aaa", "m2")
test("aaa", "m2")
test("aaa", "m1")

# But as soon as you try to create a mapset with a different name
# pygrass will no longer be able to resolve map names.
test("bbb", "m1")       # this will fail

As soon as you figure out what the problem is, it is not difficult to work around it. In this case You just need to specify the mapset name when you create the RasterRow instance. I.e. if you apply the following patch, the function will no longer raise an Exception:

-        r = pygrass.raster.RasterRow(map_name)
+        r = pygrass.raster.RasterRow(map_name, mapset_name)

I guess that the same is true for pygrass.utils.get_mapset_raster() and possible other similar function and classes.

If I have understood this correctly, the problem seems to be in the G_find_raster*() functions which for some reason seem to "get stuck" to the initial mapset name.

  1. Is this documented and I somehow completely missed that?
  2. When creating a new mapset, do we need to call some function from e.g. grass.lib.gis in order to get name resolution working?
  3. If not, should we make get_mapset_raster and friends explicitly pass the current mapset to G_find_raster*() if a mapset has not been specified?

Change History (1)

comment:1 by neteler, 4 years ago

Milestone: 7.8.3
Note: See TracTickets for help on using tickets.