Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

g.gui.gmodeler: add PyWPS export option #1919

Merged
merged 27 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6381a9e
add PyWPS export to gmodeler
pesekon2 Oct 2, 2021
6871ca8
delete pending lines at the end of two files
pesekon2 Oct 2, 2021
67fc7b2
add a forgotten change
pesekon2 Oct 2, 2021
0f50cd0
kneel for the BLM formatting
pesekon2 Oct 3, 2021
cb9fb4f
did not kneel down enough for the BLM formatting
pesekon2 Oct 3, 2021
f17930c
Apply language suggestions for the manual
pesekon2 Oct 3, 2021
3d140e8
change one of the contacts to use the keyword
pesekon2 Oct 21, 2021
cb0634c
reorder buttons in the gmodeler Python editor
pesekon2 Oct 21, 2021
aa738ab
add fallback format and extension for 3D exports
pesekon2 Oct 21, 2021
98275d0
update figures in the docs
pesekon2 Oct 21, 2021
024d3cd
fix duplicate pywps.app.Model initialization
pesekon2 Dec 2, 2021
bdc5f35
move pywps.app.Service to if __name__ block
pesekon2 Dec 2, 2021
9b4108c
Apply Vero's docs suggestions
pesekon2 Dec 3, 2021
cb431fc
docs: errors is written -> errors are written
pesekon2 Dec 3, 2021
1634cec
docs: join two sentences into one to make the connection clear
pesekon2 Dec 3, 2021
7028d12
PyWPS export: do not ComplexOutput blank unparameterized parameters
pesekon2 May 23, 2022
8a0fd23
PyWPS export: make Black lives matter
pesekon2 May 23, 2022
2fc8692
fix PyWPS not supporting default for ComplexOutput
pesekon2 Jun 5, 2022
bd074f0
PyWPS export: standardize blank lines between variables
pesekon2 Jun 6, 2022
8868761
make Black lives matter
pesekon2 Jun 6, 2022
0282c38
fix a bug introduced in 8868761
pesekon2 Sep 8, 2022
a249d85
propagate model's global overwrite value to PyWPS *.out.* exports
pesekon2 Sep 17, 2022
b176b82
PyWPS export: limit supported formats
pesekon2 Sep 17, 2022
7db28b5
make Black lives matter
pesekon2 Sep 17, 2022
3aabc6f
modeler PyWPS: write overwrite parameter only if it is True
pesekon2 Oct 7, 2022
1eede5a
gmodeler docs: OSGeoREL -> GeoForAll Lab
pesekon2 Oct 8, 2022
b85884e
add appropriate contact to docs
pesekon2 Oct 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 153 additions & 77 deletions gui/wxpython/gmodeler/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
(>=v2). Read the file COPYING that comes with GRASS for details.

@author Martin Landa <landa.martin gmail.com>
@author Python parameterization Ondrej Pesek <pesej.ondrek gmail.com>
@PyWPS, Python parameterization Ondrej Pesek <pesej.ondrek gmail.com>
"""

import os
Expand Down Expand Up @@ -246,9 +246,23 @@ def OnPageChanged(self, event):
self.pythonPanel.RefreshScript()

if self.pythonPanel.IsModified():
self.SetStatusText(_("Python script contains local modifications"), 0)
self.SetStatusText(
_(
"{} script contains local modifications".format(
self.pythonPanel.body.script_type
)
),
0,
)
else:
self.SetStatusText(_("Python script is up-to-date"), 0)
self.SetStatusText(
_(
"{} script is up-to-date".format(
self.pythonPanel.body.script_type
)
),
0,
)
elif page == self.notebook.GetPageIndexByName("items"):
self.itemPanel.Update()

Expand Down Expand Up @@ -1981,13 +1995,19 @@ def OnMoveItemsDown(self, event):


class PythonPanel(wx.Panel):
"""Model as a Python script of choice."""

def __init__(self, parent, id=wx.ID_ANY, **kwargs):
"""Model as python script"""
"""Initialize the panel."""
self.parent = parent

wx.Panel.__init__(self, parent=parent, id=id, **kwargs)

self.filename = None # temp file to run
# variable for a temp file to run Python scripts
self.filename = None
# default values of variables that will be changed if the desired
# script type is changed
self.write_object = WritePythonFile

self.bodyBox = StaticBox(
parent=self, id=wx.ID_ANY, label=" %s " % _("Python script")
Expand All @@ -1997,19 +2017,33 @@ def __init__(self, parent, id=wx.ID_ANY, **kwargs):
SetDarkMode(self.body)

self.btnRun = Button(parent=self, id=wx.ID_ANY, label=_("&Run"))
self.btnRun.SetToolTip(_("Run python script"))
self.btnRun.SetToolTip(_("Run script"))
self.Bind(wx.EVT_BUTTON, self.OnRun, self.btnRun)
self.btnSaveAs = Button(parent=self, id=wx.ID_SAVEAS)
self.btnSaveAs.SetToolTip(_("Save python script to file"))
self.btnSaveAs.SetToolTip(_("Save the script to a file"))
self.Bind(wx.EVT_BUTTON, self.OnSaveAs, self.btnSaveAs)
self.btnRefresh = Button(parent=self, id=wx.ID_REFRESH)
self.btnRefresh.SetToolTip(
_(
"Refresh python script based on the model.\n"
"It will discards all local changes."
"Refresh the script based on the model.\n"
"It will discard all local changes."
)
)
self.script_type_box = wx.Choice(
parent=self,
id=wx.ID_ANY,
choices=[
_("Python"),
_("PyWPS"),
],
)
self.script_type_box.SetSelection(0) # Python
self.Bind(wx.EVT_BUTTON, self.OnRefresh, self.btnRefresh)
self.Bind(
wx.EVT_CHOICE,
self.OnChangeScriptType,
self.script_type_box,
)

self._layout()

Expand All @@ -2024,6 +2058,13 @@ def _layout(self):
btnSizer.AddStretchSpacer()
btnSizer.Add(self.btnSaveAs, proportion=0, flag=wx.RIGHT, border=5)
btnSizer.Add(self.btnRun, proportion=0, flag=wx.RIGHT, border=5)
btnSizer.Add(
StaticText(
parent=self, id=wx.ID_ANY, label="%s:" % _("Python script type")
),
flag=wx.ALIGN_CENTER_VERTICAL,
)
btnSizer.Add(self.script_type_box, proportion=0, flag=wx.RIGHT, border=5)

sizer.Add(bodySizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=3)
Expand All @@ -2032,44 +2073,45 @@ def _layout(self):
sizer.SetSizeHints(self)
self.SetSizer(sizer)

def OnRun(self, event):
"""Run Python script"""
self.filename = grass.tempfile()
try:
fd = open(self.filename, "w")
fd.write(self.body.GetText())
except IOError as e:
GError(_("Unable to launch Python script. %s") % e, parent=self)
return
finally:
fd.close()
mode = stat.S_IMODE(os.lstat(self.filename)[stat.ST_MODE])
os.chmod(self.filename, mode | stat.S_IXUSR)
def RefreshScript(self):
"""Refresh the script.

for item in self.parent.GetModel().GetItems():
if (
len(item.GetParameterizedParams()["params"])
+ len(item.GetParameterizedParams()["flags"])
> 0
):
self.parent._gconsole.RunCmd(
[fd.name, "--ui"], skipInterface=False, onDone=self.OnDone
)
break
else:
self.parent._gconsole.RunCmd(
[fd.name], skipInterface=True, onDone=self.OnDone
:return: True on refresh
:return: False script hasn't been updated
"""
if len(self.parent.GetModel().GetItems()) == 0:
# no need to fully parse an empty script
self.body.SetText("")
return True

if self.body.modified:
dlg = wx.MessageDialog(
self,
message=_(
"{} script is locally modified. "
"Refresh will discard all changes. "
"Do you really want to continue?".format(self.body.script_type)
),
caption=_("Update"),
style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE,
)
ret = dlg.ShowModal()
dlg.Destroy()
if ret == wx.ID_NO:
return False

event.Skip()
fd = tempfile.TemporaryFile(mode="r+")
self.write_object(fd, self.parent.GetModel())
fd.seek(0)
self.body.SetText(fd.read())
fd.close()

def OnDone(self, event):
"""Python script finished"""
try_remove(self.filename)
self.filename = None
self.body.modified = False

return True

def SaveAs(self, force=False):
"""Save python script to file
"""Save the script to a file.

:return: filename
"""
Expand Down Expand Up @@ -2112,7 +2154,7 @@ def SaveAs(self, force=False):
fd = open(filename, "w")
try:
if force:
WritePythonFile(fd, self.parent.GetModel())
self.write_object(fd, self.parent.GetModel())
else:
fd.write(self.body.GetText())
finally:
Expand All @@ -2123,53 +2165,87 @@ def SaveAs(self, force=False):

return filename

def OnSaveAs(self, event):
"""Save python script to file"""
self.SaveAs(force=False)
event.Skip()

def RefreshScript(self):
"""Refresh Python script
def OnRun(self, event):
"""Run Python script"""
self.filename = grass.tempfile()
try:
fd = open(self.filename, "w")
fd.write(self.body.GetText())
except IOError as e:
GError(_("Unable to launch Python script. %s") % e, parent=self)
return
finally:
fd.close()
mode = stat.S_IMODE(os.lstat(self.filename)[stat.ST_MODE])
os.chmod(self.filename, mode | stat.S_IXUSR)

:return: True on refresh
:return: False script hasn't been updated
"""
if self.body.modified:
dlg = wx.MessageDialog(
self,
message=_(
"Python script is locally modificated. "
"Refresh will discard all changes. "
"Do you really want to continue?"
),
caption=_("Update"),
style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE,
for item in self.parent.GetModel().GetItems():
if (
len(item.GetParameterizedParams()["params"])
+ len(item.GetParameterizedParams()["flags"])
> 0
):
self.parent._gconsole.RunCmd(
[fd.name, "--ui"], skipInterface=False, onDone=self.OnDone
)
break
else:
self.parent._gconsole.RunCmd(
[fd.name], skipInterface=True, onDone=self.OnDone
)
ret = dlg.ShowModal()
dlg.Destroy()
if ret == wx.ID_NO:
return False

fd = tempfile.TemporaryFile(mode="r+")
WritePythonFile(fd, self.parent.GetModel())
fd.seek(0)
self.body.SetText(fd.read())
fd.close()
event.Skip()

self.body.modified = False
def OnDone(self, event):
"""Python script finished"""
try_remove(self.filename)
self.filename = None

return True
def OnChangeScriptType(self, event):
new_script_type = self.script_type_box.GetStringSelection()
if new_script_type == "Python":
self.write_object = WritePythonFile
elif new_script_type == "PyWPS":
self.write_object = WritePyWPSFile

if self.RefreshScript():
self.body.script_type = new_script_type
self.parent.SetStatusText(
_("{} script is up-to-date".format(self.body.script_type)),
0,
)

self.script_type_box.SetStringSelection(self.body.script_type)

if self.body.script_type == "Python":
self.write_object = WritePythonFile
self.btnRun.Enable()
self.btnRun.SetToolTip(_("Run script"))
elif self.body.script_type == "PyWPS":
self.write_object = WritePyWPSFile
self.btnRun.Disable()
self.btnRun.SetToolTip(
_("Run script - enabled only for basic Python scripts")
)

def OnRefresh(self, event):
"""Refresh Python script"""
"""Refresh the script."""
if self.RefreshScript():
self.parent.SetStatusText(_("Python script is up-to-date"), 0)
self.parent.SetStatusText(
_("{} script is up-to-date".format(self.body.script_type)),
0,
)
event.Skip()

def OnSaveAs(self, event):
"""Save the script to a file."""
self.SaveAs(force=False)
event.Skip()

def IsModified(self):
"""Check if python script has been modified"""
"""Check if the script has been modified."""
return self.body.modified

def IsEmpty(self):
"""Check if python script is empty"""
"""Check if the script is empty."""
return len(self.body.GetText()) == 0
Loading