From 67be6d045205b8bbbd89442271767f5b3061e57d Mon Sep 17 00:00:00 2001 From: wwj718 Date: Tue, 28 Feb 2023 11:43:34 +0800 Subject: [PATCH] support python function(call from snap!) --- extensions_v3/extension_python.py | 77 +++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/extensions_v3/extension_python.py b/extensions_v3/extension_python.py index 8c6ab9e..1425944 100644 --- a/extensions_v3/extension_python.py +++ b/extensions_v3/extension_python.py @@ -1,16 +1,12 @@ -''' -当前插件只允许运行表达式 -如果你希望执行任意python代码,请使用: https://github.com/CodeLabClub/codelab_adapter_extensions/blob/master/extensions_v2/extension_python_kernel_exec.py,注意风险 -安全性原则: 打开这个插件前,提醒社区用户确认积木中没有危险的Python代码, 允许社区成员举报危险代码 -也可以在Scratch EIM插件中运行Python代码 -''' - +import sys import time import webbrowser import requests +from io import StringIO +import contextlib from codelab_adapter.core_extension import Extension from codelab_adapter.utils import verify_token, open_path_in_system_file_manager - +from codelab_adapter.config import settings class PyHelper: def open_url(self, url, **kwargs): @@ -28,14 +24,47 @@ class PythonKernelExtension(Extension): NODE_ID = "eim/extension_python" HELP_URL = "http://adapter.codelab.club/extension_guide/extension_python_kernel/" WEIGHT = 95 - VERSION = "1.1" # extension version - DESCRIPTION = "Python eval" + VERSION = "1.2" # extension version, support python function + DESCRIPTION = "Python eval/exec(function)" def __init__(self, **kwargs): super().__init__(**kwargs) self.PyHelper = PyHelper() + self.error_prefix = "error: " - def run_python_code(self, code): + @contextlib.contextmanager + def stdoutIO(self, stdout=None): + old = sys.stdout + if stdout is None: + stdout = StringIO() + sys.stdout = stdout + yield stdout + sys.stdout = old + + def run_python_code_with_exec(self, code): + # global + try: + with self.stdoutIO() as s: + # 'hello world'[::-1] + # import re; print(re.search('just4fun', 'blog.just4fun.site').span()) + # exec(object[, globals[, locals]]) + exec(code, globals()) + output = s.getvalue() + except Exception as e: + # todo error begin + output = self.error_prefix + str(e) + return output + + def run_python_code_with_function_eval(self, code): + try: + # eval(expression, globals=None, locals=None) + output = eval(code, globals()) + except Exception as e: + # todo error begin + output = self.error_prefix + str(e) + return output + + def run_python_code_old(self, code): try: # eval(expression, globals=None, locals=None) output = eval(code, {"__builtins__": None}, { @@ -43,18 +72,36 @@ class PythonKernelExtension(Extension): "requests": requests, }) except Exception as e: - output = str(e) + output = self.error_prefix + str(e) return output # @verify_token def extension_message_handle(self, topic, payload): self.logger.info(f'python code: {payload["content"]}') - python_code = payload["content"] - output = self.run_python_code(python_code) + content = payload["content"] # eval/exec + + if (len(payload["content"]) > 5) and (content[0:4] in ['exec', 'eval']): + # cheak token + if payload["token"] != settings.token: + output = self.error_prefix + "token is invalid" + else: + run_with = content[0:4] + python_code = content[5:] + + if run_with == 'eval': + output = self.run_python_code_with_function_eval(python_code) + if run_with == 'exec': + # todo create function(from client) 4 space + # verify_token + output = self.run_python_code_with_exec(python_code) + else: + # old eval + python_code = content + output = self.run_python_code_old(python_code) try: output = str(output) # 不要传递复杂结构 except Exception as e: - output = str(e) + output = self.error_prefix + str(e) payload["content"] = output message = {"payload": payload} self.publish(message)