diff --git a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py --- a/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py +++ b/plugins/extensions/pykrita/plugin/plugins/scripter/ui_scripter/actions/runaction/runaction.py @@ -5,6 +5,7 @@ from . import docwrapper import os from scripter import resources_rc +import importlib.util class RunAction(QAction): @@ -28,16 +29,33 @@ return 'toolBar' def run(self): + """ This method execute python code from an activeDocument (file) or direct + from editor (ui_scripter/editor/pythoneditor.py). When executing code + from a file, we use importlib to load this module/file and with + "users_script" name. That's implementation seeks for a "main()" function in the script. + When executing code from editor without creating a file, we compile + this script to bytecode and we execute this in an empty scope. That's + faster than use exec directly and cleaner, because we are using an empty scope. """ + self.scripter.uicontroller.setActiveWidget('OutPut') stdout = sys.stdout stderr = sys.stderr output = docwrapper.DocWrapper(self.output.document()) output.write("======================================\n") sys.stdout = output sys.stderr = output script = self.editor.document().toPlainText() + document = self.scripter.documentcontroller.activeDocument try: - exec(script) + if document: + spec = importlib.util.spec_from_file_location("users_script", document.filePath) + users_module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(users_module) + users_module.main() + else: + code = compile(script, '', 'exec') + empty_scope = {} + exec(script, {}) except Exception as e: self.scripter.uicontroller.showException(str(e)) sys.stdout = stdout