[GRASS-dev] Using a dynamic text in module header for parser

Hi,

I would like to fill:

#% options:

and

#% answer

in a parser option for a python script dynamically. In particular I want to have tickboxes for available mapsets in the module GUI…

Meaning something like this (but less complex / not interactive):

http://permalink.gmane.org/gmane.comp.gis.grass.gui/667

My amateur programming skills do unfortunately not allow me to really understand how to accomplish what Glynn describes in the post above…

I tried to generate and run a temporary python script from within my script like this:

def main():

answer = grass.mapsets(search_path = True)

available_mapsets = str(grass.mapsets())

with tempfile.NamedTemporaryFile(delete = False) as s:

s.write(‘’’ #!/usr/bin/env python

-- coding: utf-8 --

Here comes the full module with header for the parser

#% options: ‘’’ + str(‘,’.join(available_mapsets))

’’’)

startcmd = 'python ’ + s.name

os.system(startcmd)

os.remove(s.name)

But that way the GUI never starts, when I call the outer script from GRASS and it seems that option never get parsed…

Any hints how to proceed?

Thanks for helping in advance.

Stefan

Hi again,

Now I found out that the parser section in the inner python script was not formated properly.

However, when I now call the inner script with ‘–ui’ I get an error:

Unable to fetch interface description for command ‘tmpjksdfjiol’

Details:

Try to set up GRASS_ADDON_PATH or GRASS_ADDON_BASE variable.

It was neither possible to run the script using grass.run_command() (on Windows).

Cheers

Stefan

···

From: grass-dev [mailto:grass-dev-bounces@lists.osgeo.org] On Behalf Of Blumentrath, Stefan
Sent: 12. oktober 2015 11:36
To: GRASS developers list (grass-dev@lists.osgeo.org) grass-dev@lists.osgeo.org
Subject: [GRASS-dev] Using a dynamic text in module header for parser

Hi,

I would like to fill:

#% options:

and

#% answer

in a parser option for a python script dynamically. In particular I want to have tickboxes for available mapsets in the module GUI…

Meaning something like this (but less complex / not interactive):

http://permalink.gmane.org/gmane.comp.gis.grass.gui/667

My amateur programming skills do unfortunately not allow me to really understand how to accomplish what Glynn describes in the post above…

I tried to generate and run a temporary python script from within my script like this:

def main():

answer = grass.mapsets(search_path = True)

available_mapsets = str(grass.mapsets())

with tempfile.NamedTemporaryFile(delete = False) as s:

s.write(‘’’ #!/usr/bin/env python

-- coding: utf-8 --

Here comes the full module with header for the parser

#% options: ‘’’ + str(‘,’.join(available_mapsets))

’’’)

startcmd = 'python ’ + s.name

os.system(startcmd)

os.remove(s.name)

But that way the GUI never starts, when I call the outer script from GRASS and it seems that option never get parsed…

Any hints how to proceed?

Thanks for helping in advance.

Stefan

Hi Stefan,
I have been meaning to implement something like this too and got your example to work with the additional step of setting the environment variable GRASS_ADDON_PATH (and under unix setting the permissions). Here is my example just parsing the first mapset it finds:

import os, tempfile, stat
import grass.script as grass

module = 'subbasins.py'

if __name__=='__main__':
answer = grass.mapsets(search_path = True)
available_mapsets = grass.mapsets()
`script=file(module,'r').read()`
with tempfile.NamedTemporaryFile(delete = False) as s:
s.write('''#!/usr/bin/env python
# -*- coding: utf-8 -*-

{script}

#%Option
#% key:{option}
#%end

'''.format(script=script,option=available_mapsets[0].lower()))
``
startcmd = 'python '+s.name
# set env variable
aoev='GRASS_ADDON_PATH'
tmpdir = os.path.basename(s.name)
if aoev in os.environ:
os.environ[aoev]=[tmpdir]+os.environ[aoev]
else:
os.environ[aoev]=[tmpdir]
# set permissions
os.chmod(s.name, os.stat(s.name).st_mode | stat.S_IEXEC)
# start module
os.system(startcmd)
os.remove(s.name)

Let me know if this works under Windows too.
Michel

···

On 10/12/2015 12:55 PM, Blumentrath, Stefan wrote:

Hi again,

Now I found out that the parser section in the inner python script was not formated properly.

However, when I now call the inner script with ‘–ui’ I get an error:

Unable to fetch interface description for command ‘tmpjksdfjiol’

Details:

Try to set up GRASS_ADDON_PATH or GRASS_ADDON_BASE variable.

It was neither possible to run the script using grass.run_command() (on Windows).

Cheers

Stefan

From: grass-dev [mailto:grass-dev-bounces@lists.osgeo.org] On Behalf Of Blumentrath, Stefan
Sent: 12. oktober 2015 11:36
To: GRASS developers list (grass-dev@lists.osgeo.org) grass-dev@lists.osgeo.org
Subject: [GRASS-dev] Using a dynamic text in module header for parser

Hi,

I would like to fill:

#% options:

and

#% answer

in a parser option for a python script dynamically. In particular I want to have tickboxes for available mapsets in the module GUI…

Meaning something like this (but less complex / not interactive):

http://permalink.gmane.org/gmane.comp.gis.grass.gui/667

My amateur programming skills do unfortunately not allow me to really understand how to accomplish what Glynn describes in the post above…

I tried to generate and run a temporary python script from within my script like this:

def main():

answer = grass.mapsets(search_path = True)

available_mapsets = str(grass.mapsets())

with tempfile.NamedTemporaryFile(delete = False) as s:

s.write(‘’’ #!/usr/bin/env python

-- coding: utf-8 --

Here comes the full module with header for the parser

#% options: ‘’’ + str(‘,’.join(available_mapsets))

’’’)

startcmd = 'python ’ + s.name

os.system(startcmd)

os.remove(s.name)

But that way the GUI never starts, when I call the outer script from GRASS and it seems that option never get parsed…

Any hints how to proceed?

Thanks for helping in advance.

Stefan

_______________________________________________
grass-dev mailing list
[grass-dev@lists.osgeo.org](mailto:grass-dev@lists.osgeo.org)
[http://lists.osgeo.org/mailman/listinfo/grass-dev](http://lists.osgeo.org/mailman/listinfo/grass-dev)

Sorry, I thought I had tested it with some changes I made afterwards, this end part works better:

startcmd = 'python '+s.name
# set env variable
tmpdir = os.path.dirname(s.name)
os.environ['GRASS_ADDON_PATH']=tmpdir
# set permissions
os.chmod(s.name, os.stat(s.name).st_mode | stat.S_IEXEC)
# start module
os.system(startcmd)
os.remove(s.name)

···

On 10/12/2015 12:55 PM, Blumentrath, Stefan wrote:

Hi again,

Now I found out that the parser section in the inner python script was not formated properly.

However, when I now call the inner script with ‘–ui’ I get an error:

Unable to fetch interface description for command ‘tmpjksdfjiol’

Details:

Try to set up GRASS_ADDON_PATH or GRASS_ADDON_BASE variable.

It was neither possible to run the script using grass.run_command() (on Windows).

Cheers

Stefan

From: grass-dev [mailto:grass-dev-bounces@lists.osgeo.org] On Behalf Of Blumentrath, Stefan
Sent: 12. oktober 2015 11:36
To: GRASS developers list (grass-dev@lists.osgeo.org) grass-dev@lists.osgeo.org
Subject: [GRASS-dev] Using a dynamic text in module header for parser

Hi,

I would like to fill:

#% options:

and

#% answer

in a parser option for a python script dynamically. In particular I want to have tickboxes for available mapsets in the module GUI…

Meaning something like this (but less complex / not interactive):

http://permalink.gmane.org/gmane.comp.gis.grass.gui/667

My amateur programming skills do unfortunately not allow me to really understand how to accomplish what Glynn describes in the post above…

I tried to generate and run a temporary python script from within my script like this:

def main():

answer = grass.mapsets(search_path = True)

available_mapsets = str(grass.mapsets())

with tempfile.NamedTemporaryFile(delete = False) as s:

s.write(‘’’ #!/usr/bin/env python

-- coding: utf-8 --

Here comes the full module with header for the parser

#% options: ‘’’ + str(‘,’.join(available_mapsets))

’’’)

startcmd = 'python ’ + s.name

os.system(startcmd)

os.remove(s.name)

But that way the GUI never starts, when I call the outer script from GRASS and it seems that option never get parsed…

Any hints how to proceed?

Thanks for helping in advance.

Stefan

_______________________________________________
grass-dev mailing list
[grass-dev@lists.osgeo.org](mailto:grass-dev@lists.osgeo.org)
[http://lists.osgeo.org/mailman/listinfo/grass-dev](http://lists.osgeo.org/mailman/listinfo/grass-dev)

Hi,

you can look how Layer manager launches scripts:
https://trac.osgeo.org/grass/browser/grass/trunk/gui/wxpython/lmgr/frame.py#L841, I think it requires setting the GRASS_ADDON_PATH

I remember this problem, maybe it’s in parser. There might be a ticket already, but I am not sure. If you can’t find anything related, please create a ticket.

···

On Tue, Oct 13, 2015 at 9:33 AM, Michel Wortmann <wortmann@pik-potsdam.de> wrote:

Hi Stefan,
I have been meaning to implement something like this too and got your example to work with the additional step of setting the environment variable GRASS_ADDON_PATH (and under unix setting the permissions). Here is my example just parsing the first mapset it finds:

import os, tempfile, stat
import grass.script as grass

module = 'subbasins.py'

if __name__=='__main__':
answer = grass.mapsets(search_path = True)
available_mapsets = grass.mapsets()
`script=file(module,'r').read()`
with tempfile.NamedTemporaryFile(delete = False) as s:
s.write('''#!/usr/bin/env python
# -*- coding: utf-8 -*-

{script}

#%Option
#% key:{option}
#%end

'''.format(script=script,option=available_mapsets[0].lower()))
``
startcmd = 'python '+[s.name](http://s.name)
# set env variable
aoev='GRASS_ADDON_PATH'
tmpdir = os.path.basename([s.name](http://s.name))
if aoev in os.environ:
os.environ[aoev]=[tmpdir]+os.environ[aoev]
else:
os.environ[aoev]=[tmpdir]
# set permissions
os.chmod([s.name](http://s.name), os.stat([s.name](http://s.name)).st_mode | stat.S_IEXEC)
# start module
os.system(startcmd)
os.remove([s.name](http://s.name))

Let me know if this works under Windows too.
Michel

On 10/12/2015 12:55 PM, Blumentrath, Stefan wrote:

Hi again,

Now I found out that the parser section in the inner python script was not formated properly.

However, when I now call the inner script with ‘–ui’ I get an error:

Unable to fetch interface description for command ‘tmpjksdfjiol’

Details:

Try to set up GRASS_ADDON_PATH or GRASS_ADDON_BASE variable.

It was neither possible to run the script using grass.run_command() (on Windows).

Cheers

Stefan

From: grass-dev [mailto:grass-dev-bounces@lists.osgeo.org] On Behalf Of Blumentrath, Stefan
Sent: 12. oktober 2015 11:36
To: GRASS developers list (grass-dev@lists.osgeo.org) grass-dev@lists.osgeo.org
Subject: [GRASS-dev] Using a dynamic text in module header for parser

Hi,

I would like to fill:

#% options:

and

#% answer

in a parser option for a python script dynamically. In particular I want to have tickboxes for available mapsets in the module GUI…

Meaning something like this (but less complex / not interactive):

http://permalink.gmane.org/gmane.comp.gis.grass.gui/667

My amateur programming skills do unfortunately not allow me to really understand how to accomplish what Glynn describes in the post above…

I tried to generate and run a temporary python script from within my script like this:

def main():

answer = grass.mapsets(search_path = True)

available_mapsets = str(grass.mapsets())

with tempfile.NamedTemporaryFile(delete = False) as s:

s.write(‘’’ #!/usr/bin/env python

-- coding: utf-8 --

Here comes the full module with header for the parser

#% options: ‘’’ + str(‘,’.join(available_mapsets))

’’’)

startcmd = 'python ’ + s.name

os.system(startcmd)

os.remove(s.name)

But that way the GUI never starts, when I call the outer script from GRASS and it seems that option never get parsed…

Any hints how to proceed?

Thanks for helping in advance.

Stefan

_______________________________________________
grass-dev mailing list
[grass-dev@lists.osgeo.org](mailto:grass-dev@lists.osgeo.org)
[http://lists.osgeo.org/mailman/listinfo/grass-dev](http://lists.osgeo.org/mailman/listinfo/grass-dev)

grass-dev mailing list
grass-dev@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/grass-dev

Hi Anna and Michel,

Thanks for looking into this and sorry for my late response.

Anna, I assume you refer to this ticket:

https://trac.osgeo.org/grass/ticket/1982

Also in my case os.chdir() did the trick.

I had both environment variables (GRASS_ADDON_PATH and GRASS_ADDON_BASE) defined, and that did not help (though I have to admit that I cannot tell for sure if the environment is passed to the execution of the “inner” python script properly. I also tried writing out an additional batch script on windows, but that did not change anything either…

Unfortunately, Michels script did not work for me on Windows (line script=file(module,‘r’).read() threw an error (plus some more further down the road)).

The script below works on Windows (at least my installation), though it gives me a pop-up window asking for the proper program to execute the specified file in the command. The pop-up can be closed and then the script continues as desired…

I hope you dont mind that I open an enhancement request for this. I saw that the “checker” structure member in the parser executes a routine (see: [https://grass.osgeo.org/programming7/gislib_cmdline_parsing.html#Complete_Structure_Members_Table](https://grass.osgeo.org/programming7/gislib_cmdline_parsing.html#Complete_Structure_Members_Table)). This is actually what I was thinking about here (If I dont misunderstand how It works), so I hope the “checker” solution could be re-purposed in this direction…?

Kind regards

Stefan

Windows solution:

#!/usr/bin/env python

-- coding: utf-8 -- import os

import stat

import tempfile

import subprocess

import grass.script as grass

from os import getenv

answer = grass.mapsets(search_path = True)

available_mapsets = grass.mapsets()

#print str(‘,’.join(grass.mapsets()))

#print str(‘,’.join(answer))

with tempfile.NamedTemporaryFile(dir=os.path.join(getenv(‘GRASS_ADDON_BASE’), ‘scripts’), suffix=‘.py’, delete = False) as s:

s.write(‘’'#!/usr/bin/env python

-- coding: utf-8 --

···

Hi,

you can look how Layer manager launches scripts:

https://trac.osgeo.org/grass/browser/grass/trunk/gui/wxpython/lmgr/frame.py#L841, I think it requires setting the GRASS_ADDON_PATH

I remember this problem, maybe it’s in parser. There might be a ticket already, but I am not sure. If you can’t find anything related, please create a ticket.

On Tue, Oct 13, 2015 at 9:33 AM, Michel Wortmann <wortmann@pik-potsdam.de> wrote:

Hi Stefan,
I have been meaning to implement something like this too and got your example to work with the additional step of setting the environment variable GRASS_ADDON_PATH (and under unix setting the permissions). Here is my example just parsing the first mapset it finds:

import os, tempfile, stat
import grass.script as grass

module = 'subbasins.py'

if __name__=='__main__':
answer = grass.mapsets(search_path = True)
available_mapsets = grass.mapsets()
`script=file(module,'r').read()`
with tempfile.NamedTemporaryFile(delete = False) as s:
s.write('''#!/usr/bin/env python
# -*- coding: utf-8 -*-

{script}

#%Option
#% key:{option}
#%end

'''.format(script=script,option=available_mapsets[0].lower()))
``
startcmd = 'python '+s.name
# set env variable
aoev='GRASS_ADDON_PATH'
tmpdir = os.path.basename(s.name)
if aoev in os.environ:
os.environ[aoev]=[tmpdir]+os.environ[aoev]
else:
os.environ[aoev]=[tmpdir]
# set permissions
os.chmod(s.name, os.stat(s.name).st_mode | stat.S_IEXEC)
# start module
os.system(startcmd)
os.remove(s.name)

Let me know if this works under Windows too.
Michel

On 10/12/2015 12:55 PM, Blumentrath, Stefan wrote:

Hi again,

Now I found out that the parser section in the inner python script was not formated properly.

However, when I now call the inner script with ‘–ui’ I get an error:

Unable to fetch interface description for command ‘tmpjksdfjiol’

Details:

Try to set up GRASS_ADDON_PATH or GRASS_ADDON_BASE variable.

It was neither possible to run the script using grass.run_command() (on Windows).

Cheers

Stefan

From: grass-dev [mailto:grass-dev-bounces@lists.osgeo.org] On Behalf Of Blumentrath, Stefan
Sent: 12. oktober 2015 11:36
To: GRASS developers list (grass-dev@lists.osgeo.org) grass-dev@lists.osgeo.org
Subject: [GRASS-dev] Using a dynamic text in module header for parser

Hi,

I would like to fill:

#% options:

and

#% answer

in a parser option for a python script dynamically. In particular I want to have tickboxes for available mapsets in the module GUI…

Meaning something like this (but less complex / not interactive):

http://permalink.gmane.org/gmane.comp.gis.grass.gui/667

My amateur programming skills do unfortunately not allow me to really understand how to accomplish what Glynn describes in the post above…

I tried to generate and run a temporary python script from within my script like this:

def main():

answer = grass.mapsets(search_path = True)

available_mapsets = str(grass.mapsets())

with tempfile.NamedTemporaryFile(delete = False) as s:

s.write(‘’’ #!/usr/bin/env python

-- coding: utf-8 --

Here comes the full module with header for the parser

#% options: ‘’’ + str(‘,’.join(available_mapsets))

’’’)

startcmd = 'python ’ + s.name

os.system(startcmd)

os.remove(s.name)

But that way the GUI never starts, when I call the outer script from GRASS and it seems that option never get parsed…

Any hints how to proceed?

Thanks for helping in advance.

Stefan

_______________________________________________
grass-dev mailing list
[grass-dev@lists.osgeo.org](mailto:grass-dev@lists.osgeo.org)
[http://lists.osgeo.org/mailman/listinfo/grass-dev](http://lists.osgeo.org/mailman/listinfo/grass-dev)

grass-dev mailing list
grass-dev@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/grass-dev

On Mon, Oct 19, 2015 at 5:47 AM, Blumentrath, Stefan <Stefan.Blumentrath@nina.no> wrote:

I hope you don`t mind that I open an enhancement request for this.

Please do. It makes a lot of sense, in C you can create interface dynamically. But writing the whole script as a file doesn’t make sense to me. Having the interface in a string and passing that to a function grass.script.core.parse_from_string() is something in between the current C and Python ways and I would go with that.

Note that there is already #2133 which is about the path issues when using GUI. Your path issues seem little bit different and may never happen if the above would be implemented.

https://trac.osgeo.org/grass/ticket/2133

I saw that the “checker” structure member in the parser executes a routine

I think the checker is checking the particular item format, not the whole thing. Thus it is unrelated to this. But good catch anyway.

Vaclav

On Mon, Oct 19, 2015 at 5:47 AM, Blumentrath, Stefan <
Stefan.Blumentrath@nina.no> wrote:

The script below works on Windows (at least my installation), though it
gives me a pop-up window asking for the proper program to execute the
specified file in the command. The pop-up can be closed and then the script
continues as desired…

I have seen this problem with any Python module in GRASS GIS two years ago,
but I've closed the created ticket #2015 it a year ago because the behavior
was random and it is not happening in general. I think it is an operating
system issue (defected by design*), so I don't see how we could fix that.

https://trac.osgeo.org/grass/ticket/2015

* Sounds like an overstatement but it is not. E.g., MS Win are not open
source and even MS is saying that no documentation can give you as much as
the actual source code (in relation to releasing Dot Net and other things
as open source).