Skip to content

grass.script: RegionManager/RegionManagerEnv: Add support for storing current region under a persistent name#7599

Open
lindakarlovska wants to merge 3 commits into
OSGeo:mainfrom
lindakarlovska:calling-region-manager-with-existing-region-name-or-region-name-persisting-after-context
Open

grass.script: RegionManager/RegionManagerEnv: Add support for storing current region under a persistent name#7599
lindakarlovska wants to merge 3 commits into
OSGeo:mainfrom
lindakarlovska:calling-region-manager-with-existing-region-name-or-region-name-persisting-after-context

Conversation

@lindakarlovska

@lindakarlovska lindakarlovska commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

This PR adds a new region_name parameter to RegionManager, enabling users to work with saved regions:

  • If region_name refers to an existing saved region and no additional g.region parameters are provided, the saved region is used directly without modification.

    Example:

    >>> with gs.RegionManager(region_name="study_area"):
    ...     gs.parse_command("r.univar", map="elevation", format="json")
    
  • If region_name is provided together with additional g.region parameters, the region is saved under that name and persists after the context exits, allowing for reuse in future operations.

    Example:

    >>> with gs.RegionManager(region_name="my_region", raster="elevation"):
    ...     gs.run_command("r.slope.aspect", elevation="elevation", slope="slope")
    

Existing usage without region_name remains the same as it was:
E.g.:

>>> with gs.RegionManager(raster="elevation"):
...     gs.run_command("r.slope.aspect", elevation="elevation", slope="slope")

EDIT:
This PR introduces a new save() method that stores the current region under a persistent name, allowing it to be reused after the context exits. This method was added to the RegionManager and RegionManagerEnv classes. It also adds more docstring examples to clarify that saved regions were already supported through the standard g.region region= parameter.

@petrasovaa

Copy link
Copy Markdown
Contributor

Wouldn't region= work?

>>> gs.run_command("g.region", n=228000)
>>> with gs.RegionManager(region="aaa"):
...     print(gs.read_command("g.region", flags="p"))
...
north:      228500
...

>>> print(gs.read_command("g.region", flags="p"))
...
north:      228000
...

Comment thread python/grass/script/raster.py
Comment thread python/grass/script/raster.py
Comment thread python/grass/script/raster.py Outdated
@lindakarlovska lindakarlovska force-pushed the calling-region-manager-with-existing-region-name-or-region-name-persisting-after-context branch from 5e6a868 to db56e25 Compare July 9, 2026 10:46
@github-actions github-actions Bot added the tests Related to Test Suite label Jul 9, 2026
@lindakarlovska lindakarlovska force-pushed the calling-region-manager-with-existing-region-name-or-region-name-persisting-after-context branch from b65ab88 to b503764 Compare July 9, 2026 10:52
@lindakarlovska

Copy link
Copy Markdown
Contributor Author

Wouldn't region= work?

>>> gs.run_command("g.region", n=228000)
>>> with gs.RegionManager(region="aaa"):
...     print(gs.read_command("g.region", flags="p"))
...
north:      228500
...

>>> print(gs.read_command("g.region", flags="p"))
...
north:      228000
...

You are right @petrasovaa, this works normally. I intuitively expected an interface similar to MaskManager (so that there would be a region_name parameter, like mask_name), and then I didn’t see any example for region= in the docstring, so I didn’t realize that it’s already covered by **kwargs.

I think we don’t necessarily need to add a region_name parameter to the API then, adding an example to the docstring should be enough. At the same time, I added a save method, which makes it possible to save the contextual region for later use (it’s basically what I originally implemented via region_name, but now I moved it into a method, which I think makes more sense overall).

@lindakarlovska lindakarlovska requested a review from wenzeslaus July 9, 2026 11:10
Comment thread python/grass/script/raster.py Outdated
Comment thread python/grass/script/raster.py Outdated
Comment thread python/grass/script/raster.py Outdated
Comment thread python/grass/script/tests/grass_script_raster_region_test.py Outdated

@petrasovaa petrasovaa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if RegionManagerEnv has the same API.

@lindakarlovska lindakarlovska changed the title grass.script: Add support for named saved regions in RegionManager grass.script: RegionManager/RegionManagerEnv: Add support for storing current region under a persistent name Jul 12, 2026
Comment on lines +93 to +100
gs.run_command(
"g.remove",
flags="f",
type="region",
name=saved_region_name,
env=session_2x2.env,
quiet=True,
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try-finally does not look right in a test and the cleanup should be done by the testing harness, i.e., the fixture. Specifically, the project will be deleted because it is in a temporary directory. No need to take care of it here.

Comment on lines +605 to +606
context usage, no region files are written to disk. If you call
:py:meth:`.save`, a named region is intentionally written to disk.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The save method disrupts the context here. It needs to be a separate note.

Comment on lines +649 to +650
is an exception and uses *g.region save=* intentionally to store
the current region persistently.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is implementation detail.

Comment on lines +627 to +633
Example saving the temporary region and reusing it later through *region=*:

>>> with gs.RegionManagerEnv(raster="elevation") as manager:
... manager.save("study_area")
>>> with gs.RegionManager(region="study_area"):
... gs.parse_command("r.univar", map="elevation", format="json")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 example don't make much sense together, I would split it as it was before and add:

gs.run_command("g.region", save="study_area", s=1000, n=1100, w=1000, e=1100)

"""Test RegionManagerEnv can persist the current region explicitly."""
saved_region_name = "saved_region_env"

try:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why try/finally here? If it fails, that's the point of the test, no? The removal is probabaly unnecessary, it's temporary session anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libraries Python Related code is in Python tests Related to Test Suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants