Skip to content

Commit

Permalink
grass.pygrass: Lazy load list of commands for module shortcuts (#3688)
Browse files Browse the repository at this point in the history
Importing _grass.pygrass.modules_ required the list to be loaded because the _shortcuts_ module is loaded by the _modules_ module. Now the list is loaded only when the _dir_ function is called for the first time.

This is using the technique from grass init file for lazy loading translations.

This allows grass.pygrass.modules to be imported without an active session, so this simplifies the GridModule tests (and its imports in general).
  • Loading branch information
wenzeslaus committed May 26, 2024
1 parent 55b2a2b commit b0a00b4
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 33 deletions.
22 changes: 17 additions & 5 deletions python/grass/pygrass/modules/shortcuts.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import fnmatch


from grass.script.core import get_commands
from grass.pygrass.modules.interface import Module

_CMDS = list(get_commands()[0])
_CMDS.sort()

def _get_commands():
"""Get a list of commands (tool names)"""
if _get_commands.list_of_commands is None:
# Retrieve and store the list during the the first call of the function.
# pylint: disable=import-outside-toplevel
from grass.script.core import get_commands

_get_commands.list_of_commands = list(get_commands()[0])
_get_commands.list_of_commands.sort()
return _get_commands.list_of_commands


# Initialize the attribute of the function to indicate
# that the data is not initialized.
_get_commands.list_of_commands = None


class MetaModule:
Expand Down Expand Up @@ -52,7 +64,7 @@ def __init__(self, prefix, cls=None):
def __dir__(self):
return [
mod[(len(self.prefix) + 1) :].replace(".", "_")
for mod in fnmatch.filter(_CMDS, "%s.*" % self.prefix)
for mod in fnmatch.filter(_get_commands(), "%s.*" % self.prefix)
]

def __getattr__(self, name):
Expand Down
29 changes: 1 addition & 28 deletions python/grass/pygrass/modules/tests/grass_pygrass_grid_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest

import grass.script as gs
from grass.pygrass.modules.grid import GridModule


def max_processes():
Expand Down Expand Up @@ -34,10 +35,6 @@ def test_processes(tmp_path, processes):
gs.run_command("r.surf.fractal", output=surface)

def run_grid_module():
# modules/shortcuts calls get_commands which requires GISBASE.
# pylint: disable=import-outside-toplevel
from grass.pygrass.modules.grid import GridModule

grid = GridModule(
"r.slope.aspect",
width=10,
Expand Down Expand Up @@ -72,10 +69,6 @@ def test_tiling_schemes(tmp_path, width, height):
gs.run_command("r.surf.fractal", output=surface)

def run_grid_module():
# modules/shortcuts calls get_commands which requires GISBASE.
# pylint: disable=import-outside-toplevel
from grass.pygrass.modules.grid import GridModule

grid = GridModule(
"r.slope.aspect",
width=width,
Expand Down Expand Up @@ -105,10 +98,6 @@ def test_overlaps(tmp_path, overlap):
gs.run_command("r.surf.fractal", output=surface)

def run_grid_module():
# modules/shortcuts calls get_commands which requires GISBASE.
# pylint: disable=import-outside-toplevel
from grass.pygrass.modules.grid import GridModule

grid = GridModule(
"r.slope.aspect",
width=10,
Expand Down Expand Up @@ -140,10 +129,6 @@ def test_cleans(tmp_path, clean, surface):
gs.run_command("r.surf.fractal", output=surface)

def run_grid_module():
# modules/shortcuts calls get_commands which requires GISBASE.
# pylint: disable=import-outside-toplevel
from grass.pygrass.modules.grid import GridModule

grid = GridModule(
"r.slope.aspect",
width=10,
Expand Down Expand Up @@ -189,10 +174,6 @@ def test_patching_backend(tmp_path, patch_backend):
)

def run_grid_module():
# modules/shortcuts calls get_commands which requires GISBASE.
# pylint: disable=import-outside-toplevel
from grass.pygrass.modules.grid import GridModule

grid = GridModule(
"v.to.rast",
width=10,
Expand Down Expand Up @@ -233,10 +214,6 @@ def test_tiling(tmp_path, width, height, processes):
gs.run_command("r.surf.fractal", output=surface)

def run_grid_module():
# modules/shortcuts calls get_commands which requires GISBASE.
# pylint: disable=import-outside-toplevel
from grass.pygrass.modules.grid import GridModule

grid = GridModule(
"r.slope.aspect",
width=width,
Expand Down Expand Up @@ -274,10 +251,6 @@ def test_patching_error(tmp_path, processes, backend):
surface = "fractal"

def run_grid_module():
# modules/shortcuts calls get_commands which requires GISBASE.
# pylint: disable=import-outside-toplevel
from grass.pygrass.modules.grid import GridModule

grid = GridModule(
"r.surf.fractal",
overlap=0,
Expand Down

0 comments on commit b0a00b4

Please sign in to comment.