Difficult-Rocket/Difficult_Rocket/utils/tools.py

219 lines
7.3 KiB
Python
Raw Normal View History

2021-09-08 23:38:34 +08:00
# -------------------------------
# Difficult Rocket
2023-01-20 14:08:12 +08:00
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
2021-09-08 23:38:34 +08:00
# All rights reserved
# -------------------------------
2021-04-02 23:31:54 +08:00
"""
2020-12-16 06:33:33 +08:00
writen by shenjackyuanjie
2021-09-08 23:38:34 +08:00
mail: 3695888@qq.com
2021-07-08 20:42:22 +08:00
github: @shenjackyuanjie
2021-09-08 23:38:34 +08:00
gitee: @shenjackyuanjie
2021-04-02 23:31:54 +08:00
"""
2020-12-16 06:33:33 +08:00
2021-08-13 12:25:29 +08:00
import os
2021-08-24 22:31:52 +08:00
import sys
import time
import math
2023-01-01 10:58:10 +08:00
import json
import logging
import configparser
2021-09-05 00:50:05 +08:00
2022-07-25 18:28:42 +08:00
from typing import Union
2022-12-26 11:46:05 +08:00
from xml.etree import ElementTree
2021-04-03 12:15:24 +08:00
2022-12-08 09:53:22 +08:00
import rtoml
2021-07-08 20:42:22 +08:00
2022-12-26 11:46:05 +08:00
from defusedxml.ElementTree import parse
2022-06-29 13:45:25 +08:00
from Difficult_Rocket.exception.unsupport import NoMoreJson5
2021-02-06 16:41:54 +08:00
# logger
2021-05-24 05:58:16 +08:00
tools_logger = logging.getLogger('part-tools')
2021-07-08 20:42:22 +08:00
"""
file configs
"""
2022-07-25 18:28:42 +08:00
file_error = {FileNotFoundError: 'no {filetype} file was founded!:\n file name: {filename}\n file_type: {filetype}\n stack: {stack}',
2022-09-04 13:53:09 +08:00
KeyError: 'no stack in {filetype} file {filename} was found! \n file type: {} \n file name: {} \n stack: {stack}',
2023-03-02 13:15:29 +08:00
Exception: 'get some {error_type} when read {filetype} file {filename}! \n file type: {} \n file name: {} \n stack: {stack}'}
2021-07-08 20:42:22 +08:00
2022-12-26 11:46:05 +08:00
def load_file(file_name: str,
stack: Union[str, list, dict, None] = None,
2023-01-01 10:58:10 +08:00
raise_error: bool = True,
2023-02-06 13:16:35 +08:00
encoding: str = 'utf-8') -> Union[dict, ElementTree.ElementTree]:
2021-07-08 20:42:22 +08:00
f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式)
2022-08-12 21:07:36 +08:00
get_file = NotImplementedError('解析失败,请检查文件类型/文件内容/文件是否存在!')
2021-07-08 20:42:22 +08:00
try:
if f_type == 'xml':
2022-12-26 11:46:05 +08:00
xml_load: ElementTree.ElementTree = parse(file_name)
2021-07-08 20:42:22 +08:00
if stack is not None:
2023-01-01 10:58:10 +08:00
get_file = xml_load.findall(stack)
2021-08-24 22:31:52 +08:00
elif (f_type == 'config') or (f_type == 'conf') or (f_type == 'ini'):
2022-03-22 21:18:04 +08:00
get_file = configparser.ConfigParser()
get_file.read(file_name)
2021-07-08 20:42:22 +08:00
if stack:
2022-03-22 21:18:04 +08:00
get_file = get_file[stack]
elif f_type == 'toml':
2023-01-01 10:58:10 +08:00
with open(file_name, mode='r', encoding=encoding) as file:
2022-12-08 09:53:22 +08:00
get_file = rtoml.load(file)
2022-12-22 10:54:28 +08:00
if stack is not None:
get_file = get_file[stack]
2023-01-01 10:58:10 +08:00
elif f_type == 'json':
with open(file_name, mode='r', encoding=encoding) as file:
get_file = json.load(file)
if stack is not None:
get_file = get_file[stack]
elif f_type == 'json5':
raise NoMoreJson5("我说什么也不用json5了喵的")
2021-07-08 20:42:22 +08:00
except Exception as exp:
2022-07-25 18:28:42 +08:00
error_type = type(exp)
2021-11-06 19:07:32 +08:00
if error_type in file_error:
tools_logger.error(file_error[error_type].format(filetype=f_type, filename=file_name, stack=stack))
else:
2022-07-25 18:28:42 +08:00
tools_logger.error(file_error[Exception].format(error_type=error_type, filetype=f_type, filename=file_name, stack=stack))
if raise_error:
2022-12-08 09:53:22 +08:00
raise exp from None
2022-03-22 21:18:04 +08:00
return get_file
2021-07-08 20:42:22 +08:00
2023-01-01 10:58:10 +08:00
def save_dict_file(file_name: str,
data: dict,
encoding: str = 'utf-8') -> bool:
f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式)
try:
if (f_type == 'config') or (f_type == 'conf') or (f_type == 'ini'):
return False
elif f_type == 'toml':
with open(file_name, mode='w', encoding=encoding) as file:
rtoml.dump(data, file)
elif f_type == 'json':
with open(file_name, mode='w', encoding=encoding) as file:
json.dump(data, file)
elif f_type == 'json5':
raise NoMoreJson5("我说什么也不用json5了喵的")
except Exception as exp:
raise exp
2021-07-08 20:42:22 +08:00
# main config
2022-12-22 10:54:28 +08:00
main_config_file = load_file('./configs/main.toml')
2021-07-08 20:42:22 +08:00
def get_At(name, in_xml, need_type=str):
"""
get Attribute from a XML tree
will raise TypeError if input is not str or list
XML json5 no! toml yes!
2021-07-08 20:42:22 +08:00
"""
name_type = type(name)
if name_type == list:
At_list = []
for need_name in name:
if in_xml.hasAttribute(need_name):
get = in_xml.getAttribute(need_name)
At_list.append(need_type(get))
else:
continue
return At_list
elif name_type == str:
if in_xml.hasAttribute(name):
2022-12-08 09:53:22 +08:00
attr = in_xml.getAttribute(name)
2021-07-08 20:42:22 +08:00
else:
return None
else:
raise TypeError('only str and list type is ok but you give me a' + name_type + 'type')
2022-12-08 09:53:22 +08:00
return need_type(attr)
2021-07-08 20:42:22 +08:00
def default_name_handler(name_: str) -> str:
"""
won't change the string
just return one
"""
name = name_
name = name.replace('{time.time}', str(time.time()))
name = name.replace('{dir}', str(os.getcwd()))
name = name.replace('{py_v}', str(sys.version.split(' ')[0]))
name = name.replace('{version}', str(main_config_file['runtime']['version']))
2021-08-13 12:25:29 +08:00
name = name.replace('{write_v}', str(main_config_file['runtime']['write_py_v']))
2021-07-08 20:42:22 +08:00
return name
2021-08-13 12:25:29 +08:00
def name_handler(name: str, formats: dict = None) -> str:
2021-07-08 20:42:22 +08:00
if formats is None:
return default_name_handler(name)
name = default_name_handler(name)
for need_replace in formats:
replace = formats[need_replace]
if need_replace == '{date}':
2021-08-13 12:25:29 +08:00
if '{date}' in formats:
replace = time.strftime(formats['{date}'], time.gmtime(time.time()))
else:
replace = time.strftime(main_config_file['runtime']['date_fmt'], time.gmtime(time.time()))
2021-07-08 20:42:22 +08:00
name = name.replace(need_replace, replace)
return name
2021-04-02 23:31:54 +08:00
"""
2021-01-23 19:55:35 +08:00
some tools
2021-04-02 23:31:54 +08:00
"""
2020-12-23 23:19:16 +08:00
2021-09-02 22:47:10 +08:00
yes = ['true', '1', 1, 1.0, True]
no = ['false', '0', 0, 0.0, False, None]
2020-12-16 06:33:33 +08:00
2021-09-02 22:47:10 +08:00
def format_bool(thing) -> bool:
"""
:param thing 啥都行只要是能传进来的都可以
如果看起来像"True" 比如 'true','1',1
就返回 True
如果看起来像"False" 比如 'false','0',0
就返回 False
都不像就 raise TypeError
感谢来自MCDReforged的各位同志你能在MCDR群里聊除了MCDR的任何东西
"""
if (thing in yes) or (isinstance(thing, str) and thing.lower() in yes):
2020-12-16 06:33:33 +08:00
return True
2021-09-02 22:47:10 +08:00
elif (thing in no) or (isinstance(thing, str) and thing.lower() in no):
2020-12-16 06:33:33 +08:00
return False
else:
2021-09-02 22:47:10 +08:00
raise TypeError("Need a 'like bool' not a {}".format(thing))
2020-12-22 18:13:59 +08:00
2020-12-23 23:19:16 +08:00
level_ = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL',
2021-04-17 01:14:38 +08:00
logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL]
2021-02-14 23:15:54 +08:00
def log_level(level):
if level in level_:
if (level == 'DEBUG') or (level == logging.DEBUG):
return logging.DEBUG
if (level == 'INFO') or (level == logging.INFO):
return logging.INFO
if (level == 'WARNING') or (level == logging.WARNING):
return logging.WARNING
if (level == 'ERROR') or (level == logging.ERROR):
return logging.ERROR
if (level == 'CRITICAL') or (level == logging.CRITICAL):
return logging.CRITICAL
else:
2021-07-08 20:42:22 +08:00
raise ValueError('Need a like logging.level thing not anything else')
2021-02-14 23:15:54 +08:00
2021-04-03 12:15:24 +08:00
2021-03-20 10:52:40 +08:00
# linear_algebra
2021-02-14 23:15:54 +08:00
2021-04-03 12:15:24 +08:00
def C_R_P(position, degrees): # stand for calculation
2021-03-20 10:52:40 +08:00
"""
2021-07-08 20:42:22 +08:00
very thanks for lenny from pyglet developer
2021-03-20 10:56:08 +08:00
https://github.com/LennyPhoenix
2021-03-20 10:52:40 +08:00
this part of code is write by him
"""
radians = degrees * (math.pi / 180)
cos = math.cos(radians)
sin = math.sin(radians)
rotated_pos = (position[0] * cos - position[1] * sin, position[0] * sin + position[1] * cos)
return rotated_pos