Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Changed how postexecution errors are handled in algorithms caling ext…
…ernal apps

Improved R error messages
  • Loading branch information
volaya committed Jul 18, 2013
1 parent 765ac75 commit 7a73307
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 84 deletions.
18 changes: 1 addition & 17 deletions python/plugins/sextante/core/AlgorithmProvider.py
Expand Up @@ -83,23 +83,7 @@ def getName(self):

def getDescription(self):
'''Returns the full name of the provider'''
return "Generic algorithm provider"

def getPostProcessingErrorMessage(self, wrongLayers):
'''Returns the message to be shown to the user when after running an algorithm for this provider,
there is a problem loading the resulting layer.
This method should analyze if the problem is caused by wrong entry data, a wrong or missing
installation of a required 3rd party app, or any other cause, and create an error response accordingly.
Message is provided as an HTML code that will be displayed to the user, and which might contains
links to installation paths for missing 3rd party apps.
- wrongLayers: a list of Output objects that could not be loaded.'''

html ="<p>Oooops! SEXTANTE could not open the following output layers</p><ul>\n"
for layer in wrongLayers:
html += '<li>' + layer.description + ': <font size=3 face="Courier New" color="ff0000">' + layer.value + "</font></li>\n"
html +="</ul><p>The above files could not be opened, which probably indicates that they were not correctly produced by the executed algorithm</p>"
html +="<p>Checking the log information might help you see why those layers were not created as expected</p>"
return html
return "Generic algorithm provider"

def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/../images/alg.png")
Expand Down
16 changes: 16 additions & 0 deletions python/plugins/sextante/core/GeoAlgorithm.py
Expand Up @@ -408,5 +408,21 @@ def getAsCommand(self):
s+=out.getValueAsCommandLineParameter() + ","
s= s[:-1] + ")"
return s

def getPostProcessingErrorMessage(self, wrongLayers):
'''Returns the message to be shown to the user when, after running this algorithm,
there is a problem loading the resulting layer.
This method should analyze if the problem is caused by wrong entry data, a wrong or missing
installation of a required 3rd party app, or any other cause, and create an error response accordingly.
Message is provided as an HTML code that will be displayed to the user, and which might contains
links to installation paths for missing 3rd party apps.
- wrongLayers: a list of Output objects that could not be loaded.'''

html ="<p>Oooops! SEXTANTE could not open the following output layers</p><ul>\n"
for layer in wrongLayers:
html += '<li>' + layer.description + ': <font size=3 face="Courier New" color="ff0000">' + layer.value + "</font></li>\n"
html +="</ul><p>The above files could not be opened, which probably indicates that they were not correctly produced by the executed algorithm</p>"
html +="<p>Checking the log information might help you see why those layers were not created as expected</p>"
return html


15 changes: 14 additions & 1 deletion python/plugins/sextante/grass/GrassAlgorithm.py
Expand Up @@ -449,7 +449,7 @@ def checkBeforeOpeningParametersDialog(self):
if msg is not None:
html = ("<p>This algorithm requires GRASS to be run."
"Unfortunately, it seems that GRASS is not installed in your system, or it is not correctly configured to be used from QGIS</p>")
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>'
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>'
return html


Expand All @@ -463,3 +463,16 @@ def checkParameterValuesBeforeExecuting(self):
func = getattr(module,'checkParameterValuesBeforeExecuting')
return func(self)


def getPostProcessingErrorMessage(self, wrongLayers):
html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers)
msg = GrassUtils.checkGrassIsInstalled(True)
html += ("<p>This algorithm requires GRASS to be run. A test to check if GRASS is correctly installed "
"and configured in your system has been performed, with the following result:</p><ul><i>")
if msg is None:
html += "GRASS seems to be correctly installed and configured</i></li></ul>"
else:
html += msg + "</i></li></ul>"
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>'

return html
13 changes: 0 additions & 13 deletions python/plugins/sextante/grass/GrassAlgorithmProvider.py
Expand Up @@ -83,19 +83,6 @@ def getName(self):
def getIcon(self):
return QIcon(os.path.dirname(__file__) + "/../images/grass.png")

def getPostProcessingErrorMessage(self, wrongLayers):
html = AlgorithmProvider.getPostProcessingErrorMessage(self, wrongLayers)
msg = GrassUtils.checkGrassIsInstalled(True)
html += ("<p>This algorithm requires GRASS to be run. A test to check if GRASS is correctly installed "
"and configured in your system has been performed, with the following result:</p><ul><i>")
if msg is None:
html += "GRASS seems to be correctly installed and configured</li></ul>"
else:
html += msg + "</i></li></ul>"
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>'

return html

def getSupportedOutputVectorLayerExtensions(self):
return ["shp"]

Expand Down
1 change: 0 additions & 1 deletion python/plugins/sextante/grass/GrassUtils.py
Expand Up @@ -325,7 +325,6 @@ def checkGrassIsInstalled(ignoreRegistrySettings=False):
if not ignoreRegistrySettings:
if settings.contains(GRASS_INSTALLED):
return

try:
from sextante import runalg
result = runalg("grass:v.voronoi", points(),False,False,"270778.60198,270855.745301,4458921.97814,4458983.8488",-1,0.0001, 0, None)
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/sextante/gui/CouldNotLoadResultsDialog.py
Expand Up @@ -42,7 +42,7 @@ def setupUi(self):
webView = QtWebKit.QWebView()
webView.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
webView.connect(webView, SIGNAL("linkClicked(const QUrl&)"), self.linkClicked)
html = self.alg.provider.getPostProcessingErrorMessage(self.wrongLayers)
html = self.alg.getPostProcessingErrorMessage(self.wrongLayers)
webView.setHtml(html)
closeButton = QtGui.QPushButton()
closeButton.setText("Close")
Expand Down
71 changes: 34 additions & 37 deletions python/plugins/sextante/r/RAlgorithm.py
Expand Up @@ -270,22 +270,19 @@ def getExportCommands(self):

def getImportCommands(self):
commands = []
# if rgdal is not available, try to install it

# just use main mirror
commands.append('options("repos"="http://cran.at.r-project.org/")')
rLibDir = "%s/rlibs" % SextanteUtils.userFolder().replace("\\","/")
if not os.path.isdir(rLibDir):
os.mkdir(rLibDir)
# .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!
commands.append('deflibloc <- .libPaths()[1]')
commands.append('.libPaths(c("%s",deflibloc))' % rLibDir )
commands.append(
'tryCatch(find.package("rgdal"), error=function(e) install.packages("rgdal", dependencies=TRUE, lib="%s"))' % rLibDir)
commands.append("library(\"rgdal\")");
#if not self.useRasterPackage or self.passFileNames:
commands.append(
'tryCatch(find.package("raster"), error=function(e) install.packages("raster", dependencies=TRUE, lib="%s"))' % rLibDir)
commands.append("library(\"raster\")");

# try to install packages if needed
packages = RUtils.getRequiredPackages(self.script)
packages.extend(['rgdal', 'raster'])
for p in packages:
commands.append(
'tryCatch(find.package("' + p +
'"), error=function(e) install.packages("' + p +'", dependencies=TRUE))')
commands.append('library("raster")')
commands.append('library("rgdal")')

for param in self.parameters:
if isinstance(param, ParameterRaster):
Expand Down Expand Up @@ -386,28 +383,28 @@ def helpFile(self):
return None

def checkBeforeOpeningParametersDialog(self):
if SextanteUtils.isWindows():
path = RUtils.RFolder()
if path == "":
return "R folder is not configured.\nPlease configure it before running R scripts."

R_INSTALLED = "R_INSTALLED"
settings = QSettings()
if settings.contains(R_INSTALLED):
return
if SextanteUtils.isWindows():
if SextanteConfig.getSetting(RUtils.R_USE64):
execDir = "x64"
else:
execDir = "i386"
command = [RUtils.RFolder() + os.sep + "bin" + os.sep + execDir + os.sep + "R.exe", "--version"]
msg = RUtils.checkRIsInstalled()
if msg is not None:
html = ("<p>This algorithm requires R to be run."
"Unfortunately, it seems that R is not installed in your system, or it is not correctly configured to be used from QGIS</p>")
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>'
return html


def getPostProcessingErrorMessage(self, wrongLayers):
html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers)
msg = RUtils.checkRIsInstalled(True)
html += ("<p>This algorithm requires R to be run. A test to check if R is correctly installed "
"and configured in your system has been performed, with the following result:</p><ul><i>")
if msg is None:
html += "GRASS seems to be correctly installed and configured</i></li></ul>"
html += "<p>The script you have executed needs the following packages:</p><ul>"
packages = RUtils.getRequiredPackages(self.script)
for p in packages:
html += '<li>' + p + '</li>'
html += "</ul><p>Make sure they are installed in your R environment before trying to execute this script.</p>"
else:
command = ["R --version"]
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT, universal_newlines=True).stdout

for line in iter(proc.readline, ""):
if "R version" in line:
settings.setValue(R_INSTALLED, True)
return
return "It seems that R is not correctly installed in your system.\nPlease install it before running R Scripts."
html += msg + "</i></li></ul>"
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>'

return html
40 changes: 40 additions & 0 deletions python/plugins/sextante/r/RUtils.py
Expand Up @@ -16,6 +16,7 @@
* *
***************************************************************************
"""
import re

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
Expand All @@ -24,6 +25,7 @@
__revision__ = '$Format:%H$'

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from sextante.core.SextanteConfig import SextanteConfig
import os
from sextante.core.SextanteUtils import mkdir, SextanteUtils
Expand Down Expand Up @@ -123,3 +125,41 @@ def getConsoleOutput():
s+="</font>\n"

return s

@staticmethod
def checkRIsInstalled(ignoreRegistrySettings=False):
if SextanteUtils.isWindows():
path = RUtils.RFolder()
if path == "":
return "R folder is not configured.\nPlease configure it before running R scripts."

R_INSTALLED = "R_INSTALLED"
settings = QSettings()
if not ignoreRegistrySettings:
if settings.contains(R_INSTALLED):
return
if SextanteUtils.isWindows():
if SextanteConfig.getSetting(RUtils.R_USE64):
execDir = "x64"
else:
execDir = "i386"
command = [RUtils.RFolder() + os.sep + "bin" + os.sep + execDir + os.sep + "R.exe", "--version"]
else:
command = ["R --version"]
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,stderr=subprocess.STDOUT, universal_newlines=True).stdout

for line in iter(proc.readline, ""):
if "R version" in line:
settings.setValue(R_INSTALLED, True)
return
html = ("<p>This algorithm requires R to be run."
"Unfortunately, it seems that R is not installed in your system, or it is not correctly configured to be used from QGIS</p>"
'<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>')
return html

@staticmethod
def getRequiredPackages(code):
regex = re.compile('library\("?(.*?)"?\)')
return regex.findall(code)

13 changes: 12 additions & 1 deletion python/plugins/sextante/saga/SagaAlgorithm.py
Expand Up @@ -362,7 +362,7 @@ def checkBeforeOpeningParametersDialog(self):
if msg is not None:
html = ("<p>This algorithm requires SAGA to be run."
"Unfortunately, it seems that SAGA is not installed in your system, or it is not correctly configured to be used from QGIS</p>")
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>'
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>'
return html


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

def getPostProcessingErrorMessage(self, wrongLayers):
html = GeoAlgorithm.getPostProcessingErrorMessage(self, wrongLayers)
msg = SagaUtils.checkSagaIsInstalled(True)
html += ("<p>This algorithm requires SAGA to be run. A test to check if SAGA is correctly installed "
"and configured in your system has been performed, with the following result:</p><ul><i>")
if msg is None:
html += "SAGA seems to be correctly installed and configured</li></ul>"
else:
html += msg + "</i></li></ul>"
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>'

return html
#===========================================================================
# def commandLineName(self):
# name = self.provider.getName().lower() + ":" + self.cmdname.lower()
Expand Down
13 changes: 0 additions & 13 deletions python/plugins/sextante/saga/SagaAlgorithmProvider.py
Expand Up @@ -99,19 +99,6 @@ def getDescription(self):
def getName(self):
return "saga"

def getPostProcessingErrorMessage(self, wrongLayers):
html = AlgorithmProvider.getPostProcessingErrorMessage(self, wrongLayers)
msg = SagaUtils.checkSagaIsInstalled(True)
html += ("<p>This algorithm requires SAGA to be run. A test to check if SAGA is correctly installed "
"and configured in your system has been performed, with the following result:</p><ul><i>")
if msg is None:
html += "SAGA seems to be correctly installed and configured</li></ul>"
else:
html += msg + "</i></li></ul>"
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>'

return html

def getSupportedOutputVectorLayerExtensions(self):
return ["shp"]

Expand Down

0 comments on commit 7a73307

Please sign in to comment.