221 lines
7.6 KiB
Python
221 lines
7.6 KiB
Python
|
|
import json
|
|||
|
|
import re
|
|||
|
|
|
|||
|
|
|
|||
|
|
class PythonCodeTreeNode:
|
|||
|
|
def __init__(self, data, parent=None, last_node=None, indentation=0, serial_number=0, extent_data=None):
|
|||
|
|
if extent_data is None:
|
|||
|
|
extent_data = {}
|
|||
|
|
self.data = data
|
|||
|
|
self.parent = parent
|
|||
|
|
self.children = []
|
|||
|
|
self.indentation = indentation
|
|||
|
|
self.extent_data = extent_data
|
|||
|
|
self.serial_number = serial_number
|
|||
|
|
self.last_node = last_node
|
|||
|
|
|
|||
|
|
|
|||
|
|
# 树结构类(非平衡非二叉树)
|
|||
|
|
class PythonCodeTreeController:
|
|||
|
|
|
|||
|
|
# 增
|
|||
|
|
@classmethod
|
|||
|
|
def add_data(cls, node):
|
|||
|
|
node.parent.children.append(node)
|
|||
|
|
|
|||
|
|
# 删
|
|||
|
|
@classmethod
|
|||
|
|
def del_data(cls):
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
# 改
|
|||
|
|
@classmethod
|
|||
|
|
def edit_data(cls):
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
# 查
|
|||
|
|
@classmethod
|
|||
|
|
def find_data(cls, root_node: PythonCodeTreeNode, i, s):
|
|||
|
|
if root_node.indentation == i and root_node.serial_number == s:
|
|||
|
|
return root_node
|
|||
|
|
for child in root_node.children:
|
|||
|
|
result = cls.find_data(child, i, s)
|
|||
|
|
if result:
|
|||
|
|
return result
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
@classmethod
|
|||
|
|
def find_data_by_path(cls, root_node, path, depth=0):
|
|||
|
|
if root_node is None:
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
components = path.split('/')
|
|||
|
|
current_node = root_node
|
|||
|
|
for component in components:
|
|||
|
|
if not component: # 跳过空的组件(例如,路径开头为 '/')
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
found = False
|
|||
|
|
for child in current_node.children:
|
|||
|
|
if child.data["name"] == component:
|
|||
|
|
current_node = child
|
|||
|
|
found = True
|
|||
|
|
break
|
|||
|
|
|
|||
|
|
if not found:
|
|||
|
|
return None # 如果未找到路径中的某个组件,返回None
|
|||
|
|
|
|||
|
|
return current_node
|
|||
|
|
|
|||
|
|
# 输出
|
|||
|
|
@classmethod
|
|||
|
|
def to_array(cls, node):
|
|||
|
|
result = {}
|
|||
|
|
if not isinstance(node, str):
|
|||
|
|
result = node.data.copy()
|
|||
|
|
result["indentation"] = node.indentation
|
|||
|
|
result["serial_number"] = node.serial_number
|
|||
|
|
result["children"] = [cls.to_array(child) for child in node.children]
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
# 输出
|
|||
|
|
@classmethod
|
|||
|
|
def to_array2(cls, node):
|
|||
|
|
result = {}
|
|||
|
|
if not isinstance(node, str):
|
|||
|
|
result = node.data.copy()
|
|||
|
|
result["indentation"] = node.indentation
|
|||
|
|
result["serial_number"] = node.serial_number
|
|||
|
|
return result
|
|||
|
|
|
|||
|
|
@classmethod
|
|||
|
|
def to_string(cls, code_json):
|
|||
|
|
code_string = ""
|
|||
|
|
# 输出当前节点的值
|
|||
|
|
if code_json['syntax_statement'] != 'Root':
|
|||
|
|
code_string += " " * (code_json["syntax_indentation"] - 4) + code_json['syntax_statement'] + "\n"
|
|||
|
|
|
|||
|
|
# 递归遍历子节点
|
|||
|
|
for child in code_json['children']:
|
|||
|
|
code_string += cls.to_string(child)
|
|||
|
|
|
|||
|
|
return code_string
|
|||
|
|
|
|||
|
|
|
|||
|
|
def group_tree_data(*args, **kwargs):
|
|||
|
|
deepest = []
|
|||
|
|
# 分组,确定序号
|
|||
|
|
group = {}
|
|||
|
|
for syntax in kwargs["code_list"]:
|
|||
|
|
# 处理字符串
|
|||
|
|
# 提取代码
|
|||
|
|
pattern = r'(\t{4}|\s{4})'
|
|||
|
|
matches = re.findall(pattern, syntax)
|
|||
|
|
# 确定深度
|
|||
|
|
indentation = len(matches) + 1
|
|||
|
|
# 确定总深度进行分组
|
|||
|
|
deepest.append(indentation)
|
|||
|
|
# 去除重复的层级
|
|||
|
|
deepest = set(deepest)
|
|||
|
|
# 确认分组数量
|
|||
|
|
for deep in deepest:
|
|||
|
|
group.update({f"group{deep}": []})
|
|||
|
|
# 输出详细分组信息
|
|||
|
|
for deep in deepest:
|
|||
|
|
serial_number = 0
|
|||
|
|
for i, syntax in enumerate(kwargs["code_list"]):
|
|||
|
|
pattern = r'(\t{4}|\s{4})'
|
|||
|
|
matches = re.findall(pattern, syntax)
|
|||
|
|
# 确定深度
|
|||
|
|
indentation = len(matches) + 1
|
|||
|
|
syntax = re.sub(pattern, "", syntax)
|
|||
|
|
|
|||
|
|
lines_data = {
|
|||
|
|
"syntax_statement": syntax, # 代码
|
|||
|
|
"syntax_indentation": indentation * 4, # python代码缩进
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if not syntax:
|
|||
|
|
continue # Skip empty lines
|
|||
|
|
|
|||
|
|
# 生成数据后进行分组
|
|||
|
|
if indentation == deep:
|
|||
|
|
node_info = {
|
|||
|
|
"lines_data": lines_data, # 内容
|
|||
|
|
"line_number": i, # 行号
|
|||
|
|
"indentation": indentation, # 深度
|
|||
|
|
"serial_number": serial_number # 序号
|
|||
|
|
}
|
|||
|
|
# 上层问题
|
|||
|
|
group[f"group{indentation}"].append(node_info)
|
|||
|
|
serial_number = serial_number + 1
|
|||
|
|
return group
|
|||
|
|
|
|||
|
|
|
|||
|
|
def api_code_transform_to_tree(*args, **kwargs):
|
|||
|
|
# 进行代码树的初始化
|
|||
|
|
root = PythonCodeTreeNode({
|
|||
|
|
"syntax_statement": "Root", # 代码
|
|||
|
|
"syntax_indentation": 0, # python代码缩进
|
|||
|
|
}, indentation=0, serial_number=0)
|
|||
|
|
parent = {}
|
|||
|
|
for group_key, group_value in kwargs["group_data"].items():
|
|||
|
|
for node in group_value:
|
|||
|
|
min_difference = float('inf')
|
|||
|
|
if f"group{node['indentation'] - 1}" in kwargs["group_data"]:
|
|||
|
|
for item in kwargs["group_data"][f"group{node['indentation'] - 1}"]:
|
|||
|
|
difference = node["line_number"] - item['line_number']
|
|||
|
|
if 1 <= difference < min_difference:
|
|||
|
|
min_difference = difference
|
|||
|
|
parent = {
|
|||
|
|
"depth": item["indentation"],
|
|||
|
|
"serial_number": item["serial_number"],
|
|||
|
|
}
|
|||
|
|
node.update({"test": parent})
|
|||
|
|
# 至此完整树数据整理完成,进入结构体
|
|||
|
|
for item in kwargs["group_data"].values():
|
|||
|
|
for ss in item:
|
|||
|
|
if ss["indentation"] == 1:
|
|||
|
|
node = PythonCodeTreeNode(ss["lines_data"], parent=root, indentation=ss["indentation"],
|
|||
|
|
serial_number=ss["serial_number"])
|
|||
|
|
else:
|
|||
|
|
parent = PythonCodeTreeController.find_data(root, ss["test"]["depth"], ss["test"]["serial_number"])
|
|||
|
|
node = PythonCodeTreeNode(ss["lines_data"], parent=parent, indentation=ss["indentation"],
|
|||
|
|
serial_number=ss["serial_number"])
|
|||
|
|
PythonCodeTreeController.add_data(node)
|
|||
|
|
return PythonCodeTreeController.to_array(root)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def api_transform_to_json(*args, **kwargs):
|
|||
|
|
code_string = kwargs["code_string"]
|
|||
|
|
code_string = re.sub(r'\s+#.*$', "", code_string, flags=re.M)
|
|||
|
|
code_string = re.sub(r'\'\'\'(.*?)\'\'\'|"""(.*?)"""', "", code_string, flags=re.M and re.S)
|
|||
|
|
code_string = re.sub(r'\n\s*\n', '\n', code_string)
|
|||
|
|
filter_str = r',\n\s+|\{\n\s+|\",\n\s+|\n\s+\"|\n\s+\}|\[\n\s+|\n\s+\]|\}\n\}\)|\(\n\s+[A-z0-9]|[A-z0-9]\n\}|({)'
|
|||
|
|
filter_code_list = re.finditer(filter_str, code_string)
|
|||
|
|
offset = 0
|
|||
|
|
for ss in filter_code_list:
|
|||
|
|
start_index = ss.start() - offset
|
|||
|
|
end_index = ss.end() - offset
|
|||
|
|
match_pattern = r'\n|\s+'
|
|||
|
|
new_code_string = code_string[:start_index] + re.sub(match_pattern, "",
|
|||
|
|
code_string[start_index:end_index]) + code_string[
|
|||
|
|
end_index:]
|
|||
|
|
offset += len(code_string) - len(new_code_string)
|
|||
|
|
code_string = new_code_string
|
|||
|
|
code_setting = code_string.split("\n")
|
|||
|
|
progress_data = group_tree_data(code_list=code_setting)
|
|||
|
|
syntax_config = api_code_transform_to_tree(group_data=progress_data)
|
|||
|
|
return syntax_config
|
|||
|
|
|
|||
|
|
|
|||
|
|
code = """
|
|||
|
|
res = in_data["ins_dict"]["information_safety"]().check_ufw_status()
|
|||
|
|
in_data["out_data"]["msg"] = "success"
|
|||
|
|
in_data["out_data"]["data"] = res
|
|||
|
|
in_data["out_data"]["code"] = 200
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
res = api_transform_to_json(code_string=code)
|
|||
|
|
print(json.dumps(res))
|