瀏覽代碼

enhancement #I95XTD python脚本无法写return脚本

everywhere.z 1 年之前
父節點
當前提交
8a2d189374

+ 0 - 1
liteflow-script-plugin/liteflow-script-python/pom.xml

@@ -24,5 +24,4 @@
             <artifactId>jython-standalone</artifactId>
         </dependency>
     </dependencies>
-
 </project>

+ 103 - 22
liteflow-script-plugin/liteflow-script-python/src/main/java/com/yomahub/liteflow/script/python/PythonScriptExecutor.java

@@ -3,39 +3,120 @@ package com.yomahub.liteflow.script.python;
 import cn.hutool.core.util.ReUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.enums.ScriptTypeEnum;
-import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
-import java.util.Arrays;
-import java.util.List;
+import com.yomahub.liteflow.script.ScriptExecuteWrap;
+import com.yomahub.liteflow.script.ScriptExecutor;
+import com.yomahub.liteflow.script.exception.ScriptLoadException;
+import org.python.core.PyCode;
+import org.python.core.PyObject;
+import org.python.core.PySystemState;
+import org.python.util.PythonInterpreter;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
  * Python脚本语言的执行器实现
  *
  * @author Bryan.Zhang
- * @since 2.9.5
+ * @since 2.12.0
  */
-public class PythonScriptExecutor extends JSR223ScriptExecutor {
+public class PythonScriptExecutor extends ScriptExecutor {
 
-	@Override
-	public ScriptTypeEnum scriptType() {
-		return ScriptTypeEnum.PYTHON;
-	}
+    private PythonInterpreter pythonInterpreter;
 
-	@Override
-	protected String convertScript(String script) {
-		String[] lineArray = script.split("\\n");
-		List<String> noBlankLineList = Arrays.stream(lineArray)
-			.filter(s -> !StrUtil.isBlank(s))
-			.collect(Collectors.toList());
+    private final String RESULT_KEY = "result";
 
-		// 用第一行的缩进的空格数作为整个代码的缩进量
-		String blankStr = ReUtil.getGroup0("^[ ]*", noBlankLineList.get(0));
+    private final Map<String, PyCode> compiledScriptMap = new HashMap<>();
 
-		// 重新构建脚本
-		StringBuilder scriptSB = new StringBuilder();
-		noBlankLineList.forEach(s -> scriptSB.append(StrUtil.format("{}\n", s.replaceFirst(blankStr, StrUtil.EMPTY))));
 
-		return scriptSB.toString();
-	}
+    @Override
+    public ScriptExecutor init(){
+        PySystemState systemState = new PySystemState();
+        systemState.setdefaultencoding("UTF-8");
+        this.pythonInterpreter = new PythonInterpreter(null, systemState);
+        return this;
+    }
 
+    @Override
+    public void load(String nodeId, String script) {
+        try {
+            PyCode pyCode = (PyCode) compile(script);
+            compiledScriptMap.put(nodeId, pyCode);
+        }
+        catch (Exception e) {
+            String errorMsg = StrUtil.format("script loading error for node[{}],error msg:{}", nodeId, e.getMessage());
+            throw new ScriptLoadException(errorMsg);
+        }
+    }
+
+    @Override
+    public void unLoad(String nodeId) {
+        compiledScriptMap.remove(nodeId);
+    }
+
+    @Override
+    public List<String> getNodeIds() {
+        return new ArrayList<>(compiledScriptMap.keySet());
+    }
+
+    @Override
+    public Object executeScript(ScriptExecuteWrap wrap) throws Exception {
+        if (!compiledScriptMap.containsKey(wrap.getNodeId())) {
+            String errorMsg = StrUtil.format("script for node[{}] is not loaded", wrap.getNodeId());
+            throw new ScriptLoadException(errorMsg);
+        }
+
+        PyCode compiledScript = compiledScriptMap.get(wrap.getNodeId());
+
+        bindParam(wrap, pythonInterpreter::set, pythonInterpreter::set);
+
+        pythonInterpreter.exec(compiledScript);
+
+        PyObject result = pythonInterpreter.get(RESULT_KEY);
+
+        if (result == null){
+            return null;
+        }
+
+        pythonInterpreter.cleanup();
+
+        switch (wrap.getCmp().getType()){
+            case BOOLEAN_SCRIPT:
+                return result.__tojava__(Boolean.class);
+            case FOR_SCRIPT:
+                return result.__tojava__(Integer.class);
+            default:
+                return result.__tojava__(Object.class);
+        }
+    }
+
+    @Override
+    public void cleanCache() {
+        compiledScriptMap.clear();
+    }
+
+    @Override
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.PYTHON;
+    }
+
+    @Override
+    public Object compile(String script) throws Exception {
+        return pythonInterpreter.compile(convertScript(script));
+    }
+
+    private String convertScript(String script) {
+        String[] lineArray = script.split("\\n");
+        List<String> noBlankLineList = Arrays.stream(lineArray)
+                .filter(s -> !StrUtil.isBlank(s))
+                .collect(Collectors.toList());
+
+        // 用第一行的缩进的空格数作为整个代码的缩进量
+        String blankStr = ReUtil.getGroup0("^[ ]*", noBlankLineList.get(0));
+
+        // 重新构建脚本
+        StringBuilder scriptSB = new StringBuilder();
+        noBlankLineList.forEach(s -> scriptSB.append(StrUtil.format("{}\n", s.replaceFirst(blankStr, StrUtil.EMPTY))));
+
+        return scriptSB.toString().replace("return", RESULT_KEY + "=");
+    }
 }

+ 2 - 1
liteflow-testcase-el/liteflow-testcase-el-script-python-springboot/src/test/java/com/yomahub/liteflow/test/script/python/common/ScriptPythonCommonELTest.java

@@ -39,8 +39,9 @@ public class ScriptPythonCommonELTest extends BaseTest {
 		DefaultContext context = response.getFirstContextBean();
 		Assertions.assertTrue(response.isSuccess());
 		Assertions.assertEquals(Integer.valueOf(30), context.getData("s1"));
-		Assertions.assertEquals("杰克", context.getData("name"));
+		Assertions.assertEquals("jack", context.getData("name"));
 		Assertions.assertEquals("hi,jack", context.getData("td"));
+		Assertions.assertEquals("中文",context.getData("s2"));
 	}
 
 	@Test