OSGeo / grass

GRASS GIS - free and open-source geospatial processing engine
https://grass.osgeo.org
Other
853 stars 311 forks source link

[Bug] Unusable parameters in Python API #2662

Closed pesekon2 closed 2 years ago

pesekon2 commented 2 years ago

Describe the bug

Parameter names of some modules written in C (r.resamp.bspline, r.walk, v.outlier) can stand for statements (exempli gratia, lambda) in Python, making it impossible to use them through the Python API.

EDIT: The same applies to Python module r.fillnulls (handled later in the code by using lambda_ = float(options["lambda"]))

To Reproduce

Using the basic NC dataset.

In:

#!/usr/bin/env python3

from grass.pygrass.modules import Module

def main():
    Module('g.region', raster='elevation')
    rules = """
    1:3:0.1:0.1
    4:5:10.:10.
    6:6:1000.0:1000.0
    7:7:0.3:0.3
    """
    Module(
        'r.recode',
        input='landuse@PERMANENT',
        output='friction',
        rules='-',
        stdin_=rules,
        overwrite=True
    )
    Module(
        'r.walk',
        flags='k',
        elevation='elevation@PERMANENT',
        friction='friction',
        output='walkcost',
        outdir='walkdir',
        start_coordinates=[635000, 220000],
        lambda=0.5,
        max_cost=10000,
        overwrite=True
    )

if __name__ == '__main__':
    main()

Out:

  File "/tmp/test.py", line 33
    lambda=0.5,
    ^^^^^^
SyntaxError: invalid syntax

Expected behavior

Work.

System description:

Possible fixes

  1. Avoid parameter names such as lambda + rename the current parameter
  2. Something smart that would deal with the current modules without breaking their API consistency (I do not know about any such way myself)

Current workaround

Use **kwargs:

```python
#!/usr/bin/env python3

from grass.pygrass.modules import Module

def main():
    Module('g.region', raster='elevation')
    rules = """
    1:3:0.1:0.1
    4:5:10.:10.
    6:6:1000.0:1000.0
    7:7:0.3:0.3
    """
    Module(
        'r.recode',
        input='landuse@PERMANENT',
        output='friction',
        rules='-',
        stdin_=rules,
        overwrite=True
    )

    kwargs = {'lambda': 0.5}

    Module(
        'r.walk',
        flags='k',
        elevation='elevation@PERMANENT',
        friction='friction',
        output='walkcost',
        outdir='walkdir',
        start_coordinates=[635000, 220000],
        max_cost=10000,
        overwrite=True,
        **kwargs
    )

if __name__ == '__main__':
    main()
ninsbl commented 2 years ago

Did you try lambda_?

pesekon2 commented 2 years ago

I thought I did. But apparently, I did something wrong (a typo, probably), because it works now. Thank you.

I'm adding the invalid label and closing the issue.