[processing] class name is not needed anymore to load scripts

This commit is contained in:
Alexander Bruy 2018-02-01 12:50:04 +02:00
parent 5ad3af592f
commit cd7bb16ad5
5 changed files with 61 additions and 27 deletions

View File

@ -52,5 +52,11 @@ class DeleteScriptAction(ContextAction):
QMessageBox.No)
if reply == QMessageBox.Yes:
filePath = ScriptUtils.findAlgorithmSource(self.itemData.__class__.__name__)
os.remove(filePath)
QgsApplication.processingRegistry().providerById("script").refreshAlgorithms()
if filePath is not None:
os.remove(filePath)
QgsApplication.processingRegistry().providerById("script").refreshAlgorithms()
else:
QgsMessageBox.warning(None,
self.tr("File not found"),
self.tr("Can not find corresponding script file.")
)

View File

@ -46,5 +46,11 @@ class EditScriptAction(ContextAction):
def execute(self):
filePath = ScriptUtils.findAlgorithmSource(self.itemData.__class__.__name__)
dlg = ScriptEditorDialog(filePath, iface.mainWindow())
dlg.show()
if filePath is not None:
dlg = ScriptEditorDialog(filePath, iface.mainWindow())
dlg.show()
else:
QgsMessageBox.warning(None,
self.tr("File not found"),
self.tr("Can not find corresponding script file.")
)

View File

@ -104,9 +104,9 @@ class ScriptAlgorithmProvider(QgsProcessingProvider):
items = os.scandir(folder)
for entry in items:
if entry.name.lower().endswith(".py") and entry.is_file():
algName = os.path.splitext(entry.name)[0]
moduleName = os.path.splitext(entry.name)[0]
filePath = os.path.abspath(os.path.join(folder, entry.name))
alg = ScriptUtils.loadAlgorithm(algName, filePath)
alg = ScriptUtils.loadAlgorithm(moduleName, filePath)
if alg is not None:
self.algs.append(alg)

View File

@ -28,6 +28,7 @@ __revision__ = '$Format:%H$'
import os
import codecs
import inspect
import traceback
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
@ -35,8 +36,8 @@ from qgis.PyQt.QtGui import QCursor
from qgis.PyQt.QtWidgets import (QMessageBox,
QFileDialog)
from qgis.gui import QgsGui
from qgis.core import QgsApplication, QgsSettings
from qgis.gui import QgsGui, QgsErrorDialog
from qgis.core import QgsApplication, QgsSettings, QgsError, QgsProcessingAlgorithm
from qgis.utils import iface, OverrideCursor
from processing.gui.AlgorithmDialog import AlgorithmDialog
@ -162,6 +163,7 @@ class ScriptEditorDialog(BASE, WIDGET):
self.saveScript(True)
def saveScript(self, saveAs):
newPath = None
if self.filePath is None or saveAs:
scriptDir = ScriptUtils.scriptsFolders()[0]
newPath, _ = QFileDialog.getSaveFileName(self,
@ -169,12 +171,13 @@ class ScriptEditorDialog(BASE, WIDGET):
scriptDir,
self.tr("Script files (*.py *.PY)"))
if newPath:
if not newPath.lower().endswith(".py"):
newPath += ".py"
if newPath:
if not newPath.lower().endswith(".py"):
newPath += ".py"
self.filePath = newPath
self.filePath = newPath
if self.filePath:
text = self.editor.text()
try:
with codecs.open(self.filePath, "w", encoding="utf-8") as f:
@ -194,10 +197,28 @@ class ScriptEditorDialog(BASE, WIDGET):
def runAlgorithm(self):
d = {}
exec(self.editor.text(), d)
try:
exec(self.editor.text(), d)
except Exception as e:
error = QgsError(traceback.format_exc(), "Processing")
QgsErrorDialog.show(error,
self.tr("Execution error")
)
return
alg = None
for k, v in d.items():
if inspect.isclass(v) and issubclass(v, QgsProcessingAlgorithm) and v.__name__ != "QgsProcessingAlgorithm":
alg = v()
break
if alg is None:
QMessageBox.warning(self,
self.tr("No script found"),
self.tr("Seems there is no valid script in the file.")
)
return
className = d["__all__"][0]
alg = d[className]()
alg.setProvider(QgsApplication.processingRegistry().providerById("script"))
alg.initAlgorithm()

View File

@ -36,6 +36,7 @@ from qgis.core import QgsProcessingAlgorithm, QgsMessageLog
from processing.core.ProcessingConfig import ProcessingConfig
from processing.tools.system import mkdir, userFolder
scriptsRegistry = dict()
SCRIPTS_FOLDERS = "SCRIPTS_FOLDERS"
@ -55,13 +56,17 @@ def scriptsFolders():
def loadAlgorithm(moduleName, filePath):
global scriptsRegistry
try:
spec = importlib.util.spec_from_file_location(moduleName, filePath)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
className = module.__all__[0]
obj = getattr(module, className)
return obj()
for x in dir(module):
obj = getattr(module, x)
if inspect.isclass(obj) and issubclass(obj, QgsProcessingAlgorithm) and obj.__name__ != "QgsProcessingAlgorithm":
scriptsRegistry[x] = filePath
return obj()
except ImportError as e:
QgsMessageLog.logMessage("Could not import script algorithm '{}' from '{}'\n{}".format(moduleName, filePath, str(e)),
"Processing",
@ -69,12 +74,8 @@ def loadAlgorithm(moduleName, filePath):
def findAlgorithmSource(className):
fileName = "{}.py".format(className)
folders = scriptsFolders()
for folder in folders:
items = os.scandir(folder)
for entry in items:
if entry.is_file() and entry.name == fileName:
return os.path.abspath(os.path.join(folder, fileName))
return None
global scriptsRegistry
try:
return scriptsRegistry[className]
except:
return None