Skip to content

Commit 7a73307

Browse files
committedJul 18, 2013
Changed how postexecution errors are handled in algorithms caling external apps
Improved R error messages
1 parent 765ac75 commit 7a73307

File tree

10 files changed

+118
-84
lines changed

10 files changed

+118
-84
lines changed
 

‎python/plugins/sextante/core/AlgorithmProvider.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,23 +83,7 @@ def getName(self):
8383

8484
def getDescription(self):
8585
'''Returns the full name of the provider'''
86-
return "Generic algorithm provider"
87-
88-
def getPostProcessingErrorMessage(self, wrongLayers):
89-
'''Returns the message to be shown to the user when after running an algorithm for this provider,
90-
there is a problem loading the resulting layer.
91-
This method should analyze if the problem is caused by wrong entry data, a wrong or missing
92-
installation of a required 3rd party app, or any other cause, and create an error response accordingly.
93-
Message is provided as an HTML code that will be displayed to the user, and which might contains
94-
links to installation paths for missing 3rd party apps.
95-
- wrongLayers: a list of Output objects that could not be loaded.'''
96-
97-
html ="<p>Oooops! SEXTANTE could not open the following output layers</p><ul>\n"
98-
for layer in wrongLayers:
99-
html += '<li>' + layer.description + ': <font size=3 face="Courier New" color="ff0000">' + layer.value + "</font></li>\n"
100-
html +="</ul><p>The above files could not be opened, which probably indicates that they were not correctly produced by the executed algorithm</p>"
101-
html +="<p>Checking the log information might help you see why those layers were not created as expected</p>"
102-
return html
86+
return "Generic algorithm provider"
10387

10488
def getIcon(self):
10589
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/alg.png")

‎python/plugins/sextante/core/GeoAlgorithm.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,5 +408,21 @@ def getAsCommand(self):
408408
s+=out.getValueAsCommandLineParameter() + ","
409409
s= s[:-1] + ")"
410410
return s
411+
412+
def getPostProcessingErrorMessage(self, wrongLayers):
413+
'''Returns the message to be shown to the user when, after running this algorithm,
414+
there is a problem loading the resulting layer.
415+
This method should analyze if the problem is caused by wrong entry data, a wrong or missing
416+
installation of a required 3rd party app, or any other cause, and create an error response accordingly.
417+
Message is provided as an HTML code that will be displayed to the user, and which might contains
418+
links to installation paths for missing 3rd party apps.
419+
- wrongLayers: a list of Output objects that could not be loaded.'''
420+
421+
html ="<p>Oooops! SEXTANTE could not open the following output layers</p><ul>\n"
422+
for layer in wrongLayers:
423+
html += '<li>' + layer.description + ': <font size=3 face="Courier New" color="ff0000">' + layer.value + "</font></li>\n"
424+
html +="</ul><p>The above files could not be opened, which probably indicates that they were not correctly produced by the executed algorithm</p>"
425+
html +="<p>Checking the log information might help you see why those layers were not created as expected</p>"
426+
return html
411427

412428

‎python/plugins/sextante/grass/GrassAlgorithm.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ def checkBeforeOpeningParametersDialog(self):
449449
if msg is not None:
450450
html = ("<p>This algorithm requires GRASS to be run."
451451
"Unfortunately, it seems that GRASS is not installed in your system, or it is not correctly configured to be used from QGIS</p>")
452-
html += '<p><a href= "http://docs.qgis.org/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure GRASS to be used with SEXTANTE</p>'
452+
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure GRASS to be used with SEXTANTE</p>'
453453
return html
454454

455455

@@ -463,3 +463,16 @@ def checkParameterValuesBeforeExecuting(self):
463463
func = getattr(module,'checkParameterValuesBeforeExecuting')
464464
return func(self)
465465

466+
467+
def getPostProcessingErrorMessage(self, wrongLayers):
468+
html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers)
469+
msg = GrassUtils.checkGrassIsInstalled(True)
470+
html += ("<p>This algorithm requires GRASS to be run. A test to check if GRASS is correctly installed "
471+
"and configured in your system has been performed, with the following result:</p><ul><i>")
472+
if msg is None:
473+
html += "GRASS seems to be correctly installed and configured</i></li></ul>"
474+
else:
475+
html += msg + "</i></li></ul>"
476+
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure GRASS to be used with SEXTANTE</p>'
477+
478+
return html

‎python/plugins/sextante/grass/GrassAlgorithmProvider.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,6 @@ def getName(self):
8383
def getIcon(self):
8484
return QIcon(os.path.dirname(__file__) + "/../images/grass.png")
8585

86-
def getPostProcessingErrorMessage(self, wrongLayers):
87-
html = AlgorithmProvider.getPostProcessingErrorMessage(self, wrongLayers)
88-
msg = GrassUtils.checkGrassIsInstalled(True)
89-
html += ("<p>This algorithm requires GRASS to be run. A test to check if GRASS is correctly installed "
90-
"and configured in your system has been performed, with the following result:</p><ul><i>")
91-
if msg is None:
92-
html += "GRASS seems to be correctly installed and configured</li></ul>"
93-
else:
94-
html += msg + "</i></li></ul>"
95-
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure GRASS to be used with SEXTANTE</p>'
96-
97-
return html
98-
9986
def getSupportedOutputVectorLayerExtensions(self):
10087
return ["shp"]
10188

‎python/plugins/sextante/grass/GrassUtils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,6 @@ def checkGrassIsInstalled(ignoreRegistrySettings=False):
325325
if not ignoreRegistrySettings:
326326
if settings.contains(GRASS_INSTALLED):
327327
return
328-
329328
try:
330329
from sextante import runalg
331330
result = runalg("grass:v.voronoi", points(),False,False,"270778.60198,270855.745301,4458921.97814,4458983.8488",-1,0.0001, 0, None)

‎python/plugins/sextante/gui/CouldNotLoadResultsDialog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def setupUi(self):
4242
webView = QtWebKit.QWebView()
4343
webView.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
4444
webView.connect(webView, SIGNAL("linkClicked(const QUrl&)"), self.linkClicked)
45-
html = self.alg.provider.getPostProcessingErrorMessage(self.wrongLayers)
45+
html = self.alg.getPostProcessingErrorMessage(self.wrongLayers)
4646
webView.setHtml(html)
4747
closeButton = QtGui.QPushButton()
4848
closeButton.setText("Close")

‎python/plugins/sextante/r/RAlgorithm.py

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -270,22 +270,19 @@ def getExportCommands(self):
270270

271271
def getImportCommands(self):
272272
commands = []
273-
# if rgdal is not available, try to install it
273+
274274
# just use main mirror
275275
commands.append('options("repos"="http://cran.at.r-project.org/")')
276-
rLibDir = "%s/rlibs" % SextanteUtils.userFolder().replace("\\","/")
277-
if not os.path.isdir(rLibDir):
278-
os.mkdir(rLibDir)
279-
# .libPaths("%s") substitutes the personal libPath with "%s"! With '.libPaths(c("%s",deflibloc))' it is added without replacing and we can use all installed R packages!
280-
commands.append('deflibloc <- .libPaths()[1]')
281-
commands.append('.libPaths(c("%s",deflibloc))' % rLibDir )
282-
commands.append(
283-
'tryCatch(find.package("rgdal"), error=function(e) install.packages("rgdal", dependencies=TRUE, lib="%s"))' % rLibDir)
284-
commands.append("library(\"rgdal\")");
285-
#if not self.useRasterPackage or self.passFileNames:
286-
commands.append(
287-
'tryCatch(find.package("raster"), error=function(e) install.packages("raster", dependencies=TRUE, lib="%s"))' % rLibDir)
288-
commands.append("library(\"raster\")");
276+
277+
# try to install packages if needed
278+
packages = RUtils.getRequiredPackages(self.script)
279+
packages.extend(['rgdal', 'raster'])
280+
for p in packages:
281+
commands.append(
282+
'tryCatch(find.package("' + p +
283+
'"), error=function(e) install.packages("' + p +'", dependencies=TRUE))')
284+
commands.append('library("raster")')
285+
commands.append('library("rgdal")')
289286

290287
for param in self.parameters:
291288
if isinstance(param, ParameterRaster):
@@ -386,28 +383,28 @@ def helpFile(self):
386383
return None
387384

388385
def checkBeforeOpeningParametersDialog(self):
389-
if SextanteUtils.isWindows():
390-
path = RUtils.RFolder()
391-
if path == "":
392-
return "R folder is not configured.\nPlease configure it before running R scripts."
393-
394-
R_INSTALLED = "R_INSTALLED"
395-
settings = QSettings()
396-
if settings.contains(R_INSTALLED):
397-
return
398-
if SextanteUtils.isWindows():
399-
if SextanteConfig.getSetting(RUtils.R_USE64):
400-
execDir = "x64"
401-
else:
402-
execDir = "i386"
403-
command = [RUtils.RFolder() + os.sep + "bin" + os.sep + execDir + os.sep + "R.exe", "--version"]
386+
msg = RUtils.checkRIsInstalled()
387+
if msg is not None:
388+
html = ("<p>This algorithm requires R to be run."
389+
"Unfortunately, it seems that R is not installed in your system, or it is not correctly configured to be used from QGIS</p>")
390+
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure R to be used with SEXTANTE</p>'
391+
return html
392+
393+
394+
def getPostProcessingErrorMessage(self, wrongLayers):
395+
html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers)
396+
msg = RUtils.checkRIsInstalled(True)
397+
html += ("<p>This algorithm requires R to be run. A test to check if R is correctly installed "
398+
"and configured in your system has been performed, with the following result:</p><ul><i>")
399+
if msg is None:
400+
html += "GRASS seems to be correctly installed and configured</i></li></ul>"
401+
html += "<p>The script you have executed needs the following packages:</p><ul>"
402+
packages = RUtils.getRequiredPackages(self.script)
403+
for p in packages:
404+
html += '<li>' + p + '</li>'
405+
html += "</ul><p>Make sure they are installed in your R environment before trying to execute this script.</p>"
404406
else:
405-
command = ["R --version"]
406-
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT, universal_newlines=True).stdout
407-
408-
for line in iter(proc.readline, ""):
409-
if "R version" in line:
410-
settings.setValue(R_INSTALLED, True)
411-
return
412-
return "It seems that R is not correctly installed in your system.\nPlease install it before running R Scripts."
407+
html += msg + "</i></li></ul>"
408+
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure R to be used with SEXTANTE</p>'
413409

410+
return html

‎python/plugins/sextante/r/RUtils.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* *
1717
***************************************************************************
1818
"""
19+
import re
1920

2021
__author__ = 'Victor Olaya'
2122
__date__ = 'August 2012'
@@ -24,6 +25,7 @@
2425
__revision__ = '$Format:%H$'
2526

2627
from PyQt4.QtGui import *
28+
from PyQt4.QtCore import *
2729
from sextante.core.SextanteConfig import SextanteConfig
2830
import os
2931
from sextante.core.SextanteUtils import mkdir, SextanteUtils
@@ -123,3 +125,41 @@ def getConsoleOutput():
123125
s+="</font>\n"
124126

125127
return s
128+
129+
@staticmethod
130+
def checkRIsInstalled(ignoreRegistrySettings=False):
131+
if SextanteUtils.isWindows():
132+
path = RUtils.RFolder()
133+
if path == "":
134+
return "R folder is not configured.\nPlease configure it before running R scripts."
135+
136+
R_INSTALLED = "R_INSTALLED"
137+
settings = QSettings()
138+
if not ignoreRegistrySettings:
139+
if settings.contains(R_INSTALLED):
140+
return
141+
if SextanteUtils.isWindows():
142+
if SextanteConfig.getSetting(RUtils.R_USE64):
143+
execDir = "x64"
144+
else:
145+
execDir = "i386"
146+
command = [RUtils.RFolder() + os.sep + "bin" + os.sep + execDir + os.sep + "R.exe", "--version"]
147+
else:
148+
command = ["R --version"]
149+
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT, universal_newlines=True).stdout
150+
151+
for line in iter(proc.readline, ""):
152+
if "R version" in line:
153+
settings.setValue(R_INSTALLED, True)
154+
return
155+
html = ("<p>This algorithm requires R to be run."
156+
"Unfortunately, it seems that R is not installed in your system, or it is not correctly configured to be used from QGIS</p>"
157+
'<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a>'
158+
'to know more about how to install and configure R to be used with SEXTANTE</p>')
159+
return html
160+
161+
@staticmethod
162+
def getRequiredPackages(code):
163+
regex = re.compile('library\("?(.*?)"?\)')
164+
return regex.findall(code)
165+

‎python/plugins/sextante/saga/SagaAlgorithm.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def checkBeforeOpeningParametersDialog(self):
362362
if msg is not None:
363363
html = ("<p>This algorithm requires SAGA to be run."
364364
"Unfortunately, it seems that SAGA is not installed in your system, or it is not correctly configured to be used from QGIS</p>")
365-
html += '<p><a href= "http://docs.qgis.org/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure SAGA to be used with SEXTANTE</p>'
365+
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure SAGA to be used with SEXTANTE</p>'
366366
return html
367367

368368

@@ -379,7 +379,18 @@ def checkParameterValuesBeforeExecuting(self):
379379
def helpFile(self):
380380
return os.path.join(os.path.dirname(__file__), "help", self.name.replace(" ", "") + ".html")
381381

382+
def getPostProcessingErrorMessage(self, wrongLayers):
383+
html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers)
384+
msg = SagaUtils.checkSagaIsInstalled(True)
385+
html += ("<p>This algorithm requires SAGA to be run. A test to check if SAGA is correctly installed "
386+
"and configured in your system has been performed, with the following result:</p><ul><i>")
387+
if msg is None:
388+
html += "SAGA seems to be correctly installed and configured</li></ul>"
389+
else:
390+
html += msg + "</i></li></ul>"
391+
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure SAGA to be used with SEXTANTE</p>'
382392

393+
return html
383394
#===========================================================================
384395
# def commandLineName(self):
385396
# name = self.provider.getName().lower() + ":" + self.cmdname.lower()

‎python/plugins/sextante/saga/SagaAlgorithmProvider.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,6 @@ def getDescription(self):
9999
def getName(self):
100100
return "saga"
101101

102-
def getPostProcessingErrorMessage(self, wrongLayers):
103-
html = AlgorithmProvider.getPostProcessingErrorMessage(self, wrongLayers)
104-
msg = SagaUtils.checkSagaIsInstalled(True)
105-
html += ("<p>This algorithm requires SAGA to be run. A test to check if SAGA is correctly installed "
106-
"and configured in your system has been performed, with the following result:</p><ul><i>")
107-
if msg is None:
108-
html += "SAGA seems to be correctly installed and configured</li></ul>"
109-
else:
110-
html += msg + "</i></li></ul>"
111-
html += '<p><a href= "http://docs.qgis.org/2.0/html/en/docs/user_manual/sextante/3rdParty.html">Click here</a> to know more about how to install and configure SAGA to be used with SEXTANTE</p>'
112-
113-
return html
114-
115102
def getSupportedOutputVectorLayerExtensions(self):
116103
return ["shp"]
117104

0 commit comments

Comments
 (0)
Please sign in to comment.