Skip to content
Permalink
Browse files
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 7a73307a2bd46fa7fec13cfd90b59697d9f4a7ab
@@ -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")
@@ -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


@@ -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


@@ -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
@@ -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"]

@@ -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)
@@ -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")
@@ -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):
@@ -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
@@ -16,6 +16,7 @@
* *
***************************************************************************
"""
import re

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
@@ -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
@@ -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)

@@ -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


@@ -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()
@@ -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"]

0 comments on commit 7a73307

Please sign in to comment.