support python function(call from snap!)

This commit is contained in:
wwj718 2023-02-28 11:43:34 +08:00 committed by GitHub
parent c4ca0238bc
commit 67be6d0452
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

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