整理文件夹及架构,加入打印机页面,octo反代有问题
This commit is contained in:
163
app/utils/conf_parse.py
Normal file
163
app/utils/conf_parse.py
Normal file
@@ -0,0 +1,163 @@
|
||||
import configparser
|
||||
import json
|
||||
import copy
|
||||
import math
|
||||
|
||||
class ConfParse:
|
||||
def __init__(self, config_def_json_files_paths):
|
||||
self.config_def_json_files_paths = config_def_json_files_paths
|
||||
self.configs = {}
|
||||
for file in self.config_def_json_files_paths:
|
||||
with open(file, 'r') as f:
|
||||
jf = json.load(f)
|
||||
if "settings" in jf:
|
||||
setting_json = jf["settings"]
|
||||
for key, value in setting_json.items():
|
||||
# print(key, value)
|
||||
all_items = self._expend_children(value["children"])
|
||||
for item_key, item_value in all_items.items():
|
||||
self.configs[item_key] = item_value
|
||||
elif "overrides" in jf:
|
||||
override_json = jf["overrides"]
|
||||
for key, value in override_json.items():
|
||||
if key in self.configs:
|
||||
for item_key, item_value in value.items():
|
||||
self.configs[key][item_key] = item_value
|
||||
else:
|
||||
self.configs[key] = value
|
||||
|
||||
def _expend_children(self, config):
|
||||
tmp_c = {}
|
||||
for key,val in config.items():
|
||||
if "children" in val:
|
||||
tmp_c.update(self._expend_children(val["children"]))
|
||||
val.pop("children", None)
|
||||
tmp_c[key] = val
|
||||
return tmp_c
|
||||
|
||||
def add_inst_cfg(self, inst_cfg_files_paths):
|
||||
copy_settings = copy.deepcopy(self.configs)
|
||||
config = configparser.ConfigParser()
|
||||
for file in inst_cfg_files_paths:
|
||||
config.read(file)
|
||||
if config.has_section('values'):
|
||||
for key, val in config.items('values'):
|
||||
v = str(val)
|
||||
if key not in copy_settings:
|
||||
copy_settings[key] = {}
|
||||
if v.startswith("="):
|
||||
copy_settings[key]["value"] = v[1:]
|
||||
else:
|
||||
copy_settings[key]["value"] = v
|
||||
return copy_settings
|
||||
|
||||
|
||||
def parse_configs(self, settings):
|
||||
class ConfigStr(str):
|
||||
def __mul__(self, other): raise TypeError()
|
||||
def __rmul__(self, other): raise TypeError()
|
||||
def __add__(self, other): raise TypeError()
|
||||
def __radd__(self, other): raise TypeError()
|
||||
def __sub__(self, other): raise TypeError()
|
||||
def __rsub__(self, other): raise TypeError()
|
||||
def __truediv__(self, other): raise TypeError()
|
||||
def __rtruediv__(self, other): raise TypeError()
|
||||
def __pow__(self, other): raise TypeError()
|
||||
def __rpow__(self, other): raise TypeError()
|
||||
|
||||
parsed_settings = copy.deepcopy(settings)
|
||||
|
||||
last_unparsed = -1
|
||||
while True:
|
||||
unparsed = 0
|
||||
|
||||
# 构建上下文环境变量上下文,用作eval的变量替换
|
||||
context = {}
|
||||
for k, v in parsed_settings.items():
|
||||
# 上下文里的变量取值:优先使用 value(如果有),否则使用 default_value
|
||||
if "value" in v:
|
||||
val = v["value"]
|
||||
elif "default_value" in v:
|
||||
val = v["default_value"]
|
||||
else:
|
||||
val = None
|
||||
|
||||
if isinstance(val, str):
|
||||
if val.lower() == "true":
|
||||
val = True
|
||||
elif val.lower() == "false":
|
||||
val = False
|
||||
else:
|
||||
try:
|
||||
val = int(val)
|
||||
except ValueError:
|
||||
try:
|
||||
val = float(val)
|
||||
except ValueError:
|
||||
val = ConfigStr(val)
|
||||
context[k] = val
|
||||
|
||||
# 自定义函数实现
|
||||
def resolveOrValue(key):
|
||||
return context.get(key)
|
||||
|
||||
def extruderValues(key):
|
||||
# 兼容简易的多挤出机查询逻辑,目前单挤出机环境下返回一个单元素列表
|
||||
return [context.get(key)]
|
||||
|
||||
def extruderValue(extruder_position, key):
|
||||
# 对于单挤出机环境或者全局配置,直接忽略 extruder_position,返回指定的 key 对应的值
|
||||
return context.get(key)
|
||||
|
||||
def defaultExtruderPosition():
|
||||
return 0
|
||||
|
||||
# 提供基础的运算函数支持
|
||||
builtin_funcs = {
|
||||
"max": max,
|
||||
"min": min,
|
||||
"abs": abs,
|
||||
"round": round,
|
||||
"int": int,
|
||||
"float": float,
|
||||
"bool": bool,
|
||||
"math": math,
|
||||
"resolveOrValue": resolveOrValue,
|
||||
"extruderValues": extruderValues,
|
||||
"extruderValue": extruderValue,
|
||||
"defaultExtruderPosition": defaultExtruderPosition
|
||||
}
|
||||
|
||||
for key, val_dict in parsed_settings.items():
|
||||
for field, field_val in val_dict.items():
|
||||
# 仅对字符串进行尝试计算
|
||||
if "type" == field:
|
||||
continue
|
||||
|
||||
if isinstance(field_val, str):
|
||||
try:
|
||||
# 如果是一个普通的纯字符串,比如分类名(如"Machine Type" ),eval可能会抛出SyntaxError或NameError
|
||||
# 如果它是一个python表达式,则会被顺利计算出结果
|
||||
evaluated = eval(field_val, {"__builtins__": builtin_funcs}, context)
|
||||
# 避免将原本只是用来作类型声明的 "int"/"float" 纯字符串,被错误求值为内置 Python type class 打断 JSON 序列化
|
||||
if evaluated != field_val and not isinstance(evaluated, type):
|
||||
if val_dict.get("type") == "str" and not isinstance(evaluated, str):
|
||||
if isinstance(evaluated, (list, dict)):
|
||||
import json
|
||||
val_dict[field] = json.dumps(evaluated).replace(" ", "")
|
||||
else:
|
||||
val_dict[field] = str(evaluated)
|
||||
else:
|
||||
val_dict[field] = evaluated
|
||||
except Exception:
|
||||
# 解析失败(例如是个普通英文字符串或者依赖还没被解开)则暂不做处理
|
||||
unparsed += 1
|
||||
|
||||
# 如果在这一轮中未解析出的表达式数量不再减少,说明已经到达极限,跳出循环
|
||||
if unparsed == last_unparsed:
|
||||
break
|
||||
last_unparsed = unparsed
|
||||
|
||||
return parsed_settings
|
||||
|
||||
|
||||
Reference in New Issue
Block a user