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