diff --git a/Difficult_Rocket/api/__init__.py b/Difficult_Rocket/api/__init__.py index d6a6b71..c51b7f0 100644 --- a/Difficult_Rocket/api/__init__.py +++ b/Difficult_Rocket/api/__init__.py @@ -14,7 +14,6 @@ gitee: @shenjackyuanjie # 单独导入的(或者就这一个有用的) from .delivery import Delivery -# lazy之后之前全部导入的(太多了写不动__all__了) -from .calculation import * +# lazy之后之前全部导入的(太多了写不动__all__了 from .scientific_unit import * diff --git a/Difficult_Rocket/api/calculation.py b/Difficult_Rocket/api/calculation.py deleted file mode 100644 index d93b2d1..0000000 --- a/Difficult_Rocket/api/calculation.py +++ /dev/null @@ -1,307 +0,0 @@ -# ------------------------------- -# Difficult Rocket -# Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com -# All rights reserved -# ------------------------------- - -""" -writen by shenjackyuanjie -mail: 3695888@qq.com -github: @shenjackyuanjie -gitee: @shenjackyuanjie -""" - -import math -import decimal - -from typing import List, Optional, Union -from decimal import Decimal - - -# linear_algebra - - -def C_R_P(position: List, degrees: List): # stand for calculation - """ - very thanks for lenny from pyglet developer - https://github.com/LennyPhoenix - 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 - - -""" -Physics calculation -""" - - -def is_decimal(A: any) -> bool: - if isinstance(A, decimal.Decimal): - return False - else: - return True - - -def F_D(A: decimal, B: decimal) -> decimal: - if is_decimal(A) and is_decimal(B): - return A / B - - -def F_Mu(A: decimal, B: decimal) -> decimal: - if is_decimal(A) and is_decimal(B): - return A * B - - -def F_Mi(A: decimal, B: decimal) -> decimal: - if is_decimal(A) and is_decimal(B): - return A - B - - -def F_A(A: decimal, B: decimal) -> decimal: - if is_decimal(A) and is_decimal(B): - return A + B - - -def D_C(listA: list, listB: list): # stand for Duplicate check - """ - usage:\n - input two list\n - the fun will do duplicate check and sort then\n - the fun won't return any thing just change the list now - """ - for unit in listB: - if unit in listA: - listA.remove(unit) - listB.remove(unit) - else: - continue - listA.sort() - listB.sort() - - -def S_C_float_check(SC): # stand for Scientific notation's float check - """ - formats: - SC list format:docs.basic_config.json:basic_number""" - while SC[0] >= 10: - SC[0] = F_D(SC[0], 10) - SC[1] += 1 - while SC[0] < 1: - SC[0] = F_Mu(SC[0], 10) - SC[1] -= 1 - - -def S_N_M(*SN): # stand for Scientific notation multiple - """ - formats: - A & B & C list format:docs.basic_config.json:basic_number""" - if len(SN) < 2: - raise TypeError('it need more than 1!') - elif len(SN) == 2: - return __S_N_M(SN[0], SN[1]) - else: - R = __S_N_M(SN[0], SN[1]) - for A in SN[2:]: - R = __S_N_M(R, A) - return R - - -def __S_N_M(A, B): - """ - formats: - A & B list format:docs.basic_config.json:basic_number""" - R = [F_Mu(A[0], B[0]), A[1] + B[1]] - S_C_float_check(R) - Unit1, Unit2 = A[2] + B[2], A[3] + B[3] - if Unit1 is None: - Unit1 = [] - D_C(Unit1, Unit2) - R += [Unit1, Unit2] - return R - - -def S_N_D(A, B): # stand for Scientific notation divided - """ - formats: - A & B list format:docs.basic_config:basic_number""" - R = [F_D(A[0], B[0]), A[1] - B[1]] - S_C_float_check(R) - Unit1, Unit2 = A[2] + B[3], A[3] + B[2] - if Unit1 is None: - Unit1 = [] - D_C(Unit1, Unit2) - R += [Unit1, Unit2] - return R - - -def G_C(M, m, R, G): # stand for gravity calculation - """ - formats: - M : ship's mass - m : planet's mass - R : distance to the planet - G : Gravitational constant - M & m & R format: docs.basic_config:basic_number - """ - g = basic_force() - A = S_N_M(M, m, G) - g = S_N_D(A, S_N_M(R, R)) - return g - - -def distance(A, B): - """ - formats: - A & B format: docs.basic_config:basic_poi - """ - poi_dis = basic_poi() - for x in A, B: - x = decimal.Decimal(str(x)) - xd = A[0] - B[0] - yd = A[1] - B[1] - poi_dis[0] = xd - poi_dis[1] = yd - # 勾股定理 - poi_dis[0] **= 2 - poi_dis[1] **= 2 - poi_dis.append(poi_dis[0] + poi_dis[1]) - poi_dis[2] **= 0.5 - return poi_dis[2] - - -def _BasicNumber(int_num=0, float_num=1, unit1=None, unit2=None) -> list: - if unit1 is None: - unit1 = [] - if unit2 is None: - unit2 = [] - if is_decimal(float_num): # is decimal class? - return [int_num, float_num, unit1, unit2] # is just return - else: - return [int_num, decimal.Decimal(str(float_num)), unit1, unit2] # no create a decimal class - - -def BasicNumber(int_num=0, float_num=1, unit1=None, unit2=None, num=1) -> list: - numbers = [] - if num > 1: - for x in range(0, num, 1): - numbers.append(_BasicNumber(int_num, float_num, unit1, unit2)) - elif num == 1: - return _BasicNumber(int_num, float_num, unit1, unit2) - else: # num < 1 - raise TypeError('you should give me a num with >= 1!') - return numbers - - -class BasicNumberClass: - def __init__(self, int_num=0, float_num=1, unit1=None, unit2=None): - self.int = int_num - self.float = decimal.Decimal(str(float_num)) - if unit1: - self.units1 = unit1 - else: - self.units1 = [] - if unit2: - self.units2 = unit2 - else: - self.units2 = [] - - def sort(self): - self.units1.sort() - self.units2.sort() - - def float_int_check(self, int_=None, float_=None): - if not int_: - int_ = 1 - if not float_: - float_ = decimal.Decimal(1.0) - while float_ > 10: - float_ / 10 - int_ + 1 - else: - while float_ < 0.1: - float_ * 10 - int_ - 1 - return [int_, float_] - - def units(self) -> list or bool: - if (self.units1 == []) and (self.units2 == []): - return None - data = self.units1 - data.append(self.units2) - return data - - def __str__(self): - return [self.float, self.int, self.units1, self.units2] - - def __add__(self, other): - o_type = type(other) - if o_type == type(self): - self.sort() - other.sort() - if self.units() == other.units(): - self_num = self.float * (10 ** self.int) - other_num = other.float * (10 ** other.float) - r_float = self_num + other_num - check = self.float_int_check(1, r_float) - self.float = check[0] - self.int = check[1] - elif o_type == type(decimal.Decimal('1.0')) and not self.units(): - pass - - def __radd__(self, other): - self.__add__(self) - - def __mul__(self, other): - pass - - def __rmul__(self, other): - self.__mul__(self) - - def __truediv__(self, other): - pass - - -def basic_poi(poi_type=None) -> list: - if poi_type is None: - return BasicNumber(unit1='m', num=2) - if poi_type == 'chunk': - return [BasicNumber(unit1='chunk', num=2), BasicNumber(unit1='m', num=2)] - - -def basic_force() -> list: - return BasicNumber(unit1='N', num=2) - - -class ScientificNumber: - """ - A class of Scientific notation - give float and integer and unit - """ - - def __init__(self, - 小数: Union[float, Decimal] = 1.0, - 指数: int = 0, - 乘单位: list = list, - 除单位: list = list): - if not isinstance(小数, Decimal): - self.小数 = Decimal(小数) - else: - self.小数 = 小数 - self.指数 = 指数 - self.乘单位 = 乘单位 - self.除单位 = 除单位 - self.check() - - def check(self): - while self.小数 > 10: - self.小数 /= 10 - self.指数 += 1 - while self.小数 < 1: - self.小数 *= 10 - self.指数 -= 1 - self.除单位.sort() - self.乘单位.sort() diff --git a/Difficult_Rocket/mods/__init__.py b/Difficult_Rocket/mod/__init__.py similarity index 100% rename from Difficult_Rocket/mods/__init__.py rename to Difficult_Rocket/mod/__init__.py diff --git a/Difficult_Rocket/mods/api/__init__.py b/Difficult_Rocket/mod/api/__init__.py similarity index 100% rename from Difficult_Rocket/mods/api/__init__.py rename to Difficult_Rocket/mod/api/__init__.py diff --git a/Difficult_Rocket/mods/api/client.py b/Difficult_Rocket/mod/api/client.py similarity index 100% rename from Difficult_Rocket/mods/api/client.py rename to Difficult_Rocket/mod/api/client.py diff --git a/Difficult_Rocket/mods/loader/__init__.py b/Difficult_Rocket/mod/loader/__init__.py similarity index 100% rename from Difficult_Rocket/mods/loader/__init__.py rename to Difficult_Rocket/mod/loader/__init__.py diff --git a/Difficult_Rocket/utils/logger.py b/Difficult_Rocket/utils/logger.py index 02a527a..29f6c8f 100644 --- a/Difficult_Rocket/utils/logger.py +++ b/Difficult_Rocket/utils/logger.py @@ -4,25 +4,17 @@ """ import re import os -import sys import time import atexit import inspect import threading -# from inspect import F -from os import PathLike from time import strftime from logging import NOTSET, DEBUG, INFO, WARNING, ERROR, FATAL from types import FrameType -from typing import Optional, Union, Dict, Iterable, Tuple, Any, List, Callable +from typing import Optional, Union, Dict, Iterable, Tuple, Any -print(os.path.abspath(os.curdir)) -os.chdir('../../') -sys.path.append('D:/githubs/DR') -sys.path.append(os.path.abspath('./Difficult_Rocket')) - -from Difficult_Rocket.utils.thread import ThreadLock +# print(os.path.abspath(os.curdir)) # 如果想要直接使用 logger 来 logging # 直接调用 logger.debug() 即可 @@ -101,9 +93,24 @@ logger_configs = { }, 'Color': { 'main_color': { - 'date': '\033[38;2;201;222;56m', - 'file': '\033[38;2;0;255;180m', - 'line': '\033[38;2;0;255;180m', + 'file_time': '\033[38;2;201;222;56m', + 'main_time': '\033[38;2;201;222;56m', + 'file_name': '\033[38;2;0;255;180m', + 'code_line': '\033[38;2;0;255;180m', + 'logger': '\033[0m', + TRACE: {'info': '\033[38;2;138;173;244m', 'message': '\033[38;2;40;40;70m'}, + FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'}, + DEBUG: {'info': '\033[38;2;133;138;149m', 'message': '\033[38;2;133;138;149m'}, + INFO: {'info': '\033[0m', 'message': '\033[0m'}, + WARNING: {'info': '\033[33m', 'message': '\033[33m'}, + ERROR: {'info': '\033[31m', 'message': '\033[31m'}, + FATAL: {'info': '\033[38;2;255;255;0;48;2;120;10;10m', 'message': '\033[38;2;255;255;0;48;2;120;10;10m'} + }, + 'DiGua_color': { + 'file_time': '\033[38;2;201;222;56m', + 'main_time': '\033[38;2;201;222;56m', + 'file_name': '\033[38;2;0;255;180m', + 'code_line': '\033[38;2;0;255;180m', 'logger': '\033[0m', TRACE: {'info': '\033[34;48;2;44;44;54m', 'message': '\033[34;48;2;40;40;70m'}, FINE: {'info': '\033[35;48;2;44;44;54m', 'message': '\033[35m'}, @@ -119,13 +126,17 @@ logger_configs = { 'mode': 'a', 'encoding': 'utf-8', 'level': TRACE, - 'file_name': './logs/{file_time}_logs.md' + 'file_name': './logs/{file_time}_logs.md', + 'cache_len': 10, + 'cache_time': 1 }, }, 'Formatter': { 'MESSAGE': { 'format': '[{main_time}] [{logger_name}] {level} | {file_name}:{code_line} | {message}' }, + 'file_name': 'no frame', + 'code_line': 'no frame', 'file_time': {'strftime': '%Y-%m-%d %H-%M'}, 'main_time': {'strftime': '%Y-%m-%d %H-%M-%S:%%S'}, # %%S 三位毫秒 ...: ... @@ -133,6 +144,23 @@ logger_configs = { } +class ThreadLock: + + def __init__(self, the_lock: threading.Lock, time_out: Union[float, int] = 1 / 60) -> None: + self.lock = the_lock + self.time_out = time_out + + def __enter__(self): + self.lock.acquire(timeout=self.time_out) + if not self.lock.locked(): + raise RuntimeError(f'Lock time Out with {self.time_out}') + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.lock.locked(): + self.lock.release() + + class ListCache: """一个线程安全的列表缓存""" @@ -189,24 +217,23 @@ class ListCache: class LogFileCache: """日志文件缓存""" - def __init__(self, file_conf: Dict, flush_time: Optional[Union[int, float]] = 1, log_cache_lens_max: int = 10): + def __init__(self, file_conf: dict, ): """ @param file_conf: 日志文件配置 - @param flush_time: 刷新日志缓存,写入文件的时长间隔 - @param log_cache_lens_max: 日志缓存在自动写入前的最大缓存长度 """ # 配置相关 self._logfile_name = os.path.abspath(format_str(file_conf['file_name'])) # log 文件名称 self.level = get_key_from_dict(file_conf, 'level', DEBUG) self.file_conf = file_conf - self.flush_time = flush_time # 缓存刷新时长 - self.cache_entries_num = log_cache_lens_max - self.started = False + self.flush_time = file_conf['cache_time'] # 缓存刷新时长 + self.cache_entries_num = file_conf['cache_len'] + self.started = True + self.running = False # 同步锁 self.cache_lock = threading.Lock() # 主锁 self.time_limit_lock = ThreadLock(self.cache_lock, time_out=1 / 60) # 直接用于 with 的主锁 - self.threaded_write = threading.Timer(1, self._log_file_time_write) # 基于 timer 的多线程 + self.threaded_write = threading.Timer(1, self._log_file_time_write, kwargs={'thread': True}) # 基于 timer 的多线程 # 日志缓存表 self.log_cache = ListCache(self.time_limit_lock) self.file_setup() @@ -222,7 +249,9 @@ class LogFileCache: def end_thread(self) -> None: """结束日志写入进程,顺手把目前的缓存写入""" self.cache_lock.acquire(blocking=True) - self.threaded_write.cancel() + if self.running: + self.threaded_write.cancel() + self.running = False self.started = False self._log_file_time_write() atexit.unregister(self.end_thread) @@ -230,20 +259,22 @@ class LogFileCache: def start_thread(self) -> None: self.threaded_write.start() self.started = True + self.running = True atexit.register(self.end_thread) @property - def logfile_name(self) -> PathLike: - self._logfile_name: PathLike + def logfile_name(self) -> str: + self._logfile_name: str return self._logfile_name @logfile_name.setter - def logfile_name(self, value: PathLike) -> None: + def logfile_name(self, value: str) -> None: with self.time_limit_lock: self._logfile_name = value - def _log_file_time_write(self) -> None: + def _log_file_time_write(self, thread: bool = False) -> None: """使用 threading.Timer 调用的定时写入日志文件的函数""" + print(f'write! {thread}{self.log_cache.cache}') if self.log_cache: with self.time_limit_lock: if self.log_cache: @@ -252,6 +283,8 @@ class LogFileCache: mode=get_key_from_dict(self.file_conf, 'mode', 'a')) as log_file: log_file.writelines(self.log_cache.cache.copy()) self.log_cache.clear() + if thread: + self.running = False def write_logs(self, string: str, flush: bool = False) -> None: self.log_cache.append(string) @@ -260,25 +293,36 @@ class LogFileCache: return None if flush: self._log_file_time_write() + if self.started and not self.running: + self.threaded_write = threading.Timer(1, self._log_file_time_write, kwargs={'thread': True}) # 基于 timer 的多线程 + self.threaded_write.start() + self.running = True class Logger: """shenjack logger""" - def __init__(self, name: str = None, level: int = None, file_conf: Dict = None, colors: Dict[Union[int, str], Dict[str, str]] = None, formats=None, **kwargs) -> None: + def __init__(self, + name: str = None, + level: int = None, + file_conf: Dict = None, + colors: Dict[Union[int, str], Dict[str, str]] = None, + formats=None) -> None: """ 配置模式: 使用 kwargs 配置 @param name: logger 名称 默认为 root @param level: logging 输出等级 默认为 DEBUG(10) - @param file_name: logging 写入文件名称 默认为 None(不写入) + @param file_conf: logger 的文件处理配置 + @param colors: dict 颜色配置 + @param formats: 格式化配置 """ self.name = name or 'root' self.level = level if level is not None else DEBUG self.colors = colors or logger_configs['Color']['main_color'] - self.formats = formats or logger_configs['Formatter'] + self.formats = formats or logger_configs['Formatter'].copy() + self.formats['logger_name'] = f'{self.colors["logger"]}{self.name}{color_reset_suffix}' if file_conf: self.file_cache = LogFileCache(file_conf=file_conf) - self.file_cache.start_thread() else: self.file_cache = False self.warn = self.warning @@ -293,6 +337,7 @@ class Logger: # self.file_cache.level if self.file_cache else False, # level >= self.level, # self.file_cache and (level >= self.file_cache.level)) + self.file_cache: Union[bool, LogFileCache] if level < self.level and self.file_cache and (level < self.file_cache.level): return None if not frame: @@ -311,26 +356,20 @@ class Logger: return None def format_text(self, level: int, text: str, frame: Optional[FrameType]) -> str: - from Difficult_Rocket import DR_option, DR_runtime level_with_color = f"[{self.colors[level]['info']}{level_name_map[level]}{color_reset_suffix}]" level_with_color = f"{level_with_color}{' ' * (9 - len_without_color_maker(level_with_color))}" formats = self.formats.copy() - formats.pop('MESSAGE') - if frame is None: - formats['file_name'] = 'no frame' - formats['code_line'] = 'no frame' - else: - formats['file_name'] = f"{self.colors['file']}{os.path.split(frame.f_code.co_filename)[-1]}{color_reset_suffix}" - formats['code_line'] = f"{self.colors['line']}{frame.f_lineno}{color_reset_suffix}" + if frame is not None: + formats['file_name'] = f"{self.colors['file_name']}{os.path.split(frame.f_code.co_filename)[-1]}{color_reset_suffix}" + formats['code_line'] = f"{self.colors['code_line']}{frame.f_lineno}{color_reset_suffix}" now_time = str(time.time()) for key, value in formats.items(): if isinstance(value, dict): if 'strftime' in value: value['strftime']: str - formats[key] = f"{self.colors['date']}{strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 4]))}{color_reset_suffix}" + formats[key] = f"{self.colors[key]}{strftime(value['strftime'].replace('%%S', now_time[now_time.find('.') + 1:now_time.find('.') + 4]))}{color_reset_suffix}" print_text = self.formats['MESSAGE']['format'].format(level_with_color=level_with_color, level=level_with_color, message=text, - logger_name=self.name, **formats) return print_text @@ -420,8 +459,36 @@ def logging_color() -> Dict: return {'info': ..., 'message': ...} -def setup_logger() -> None: - ... +def gen_file_conf(file_name: str, + file_level: int = DEBUG, + file_mode: str = 'a', + file_encoding: str = 'utf-8', + file_cache_len: int = 10, + file_cache_time: Union[int, float] = 1) -> dict: + return {'file_name': file_name, + 'level': file_level, + 'mode': file_mode, + 'encoding': file_encoding, + 'cache_len': file_cache_len, + 'cache_time': file_cache_time} + + +def gen_color_conf(**colors) -> dict: + default_color = logger_configs['Color']['main_color'].copy() + default_color.update(colors) + return default_color + + +def logger_with_default_settings(name: str, + level: int = DEBUG, + file_conf: dict = None, + colors: dict = None, + formats: dict = None) -> Logger: + return Logger(name=name, + level=level, + file_conf=gen_file_conf(**file_conf), + colors=gen_color_conf(**colors), + formats=logger_configs['Formatter'].copy().update(formats)) def add_dict_config_to_global(some_dict: Union[dict, list, str], name: str) -> dict: @@ -437,15 +504,6 @@ def add_dict_config_to_global(some_dict: Union[dict, list, str], name: str) -> d return logger_configs # 修改过的 logger 配置 -def add_kwargs_to_global(**kwargs) -> dict: - """ - - @param kwargs: 你要改的 logger配置 - @return: 修改过的 logger 配置 - """ - ... - - def get_logger(name: str = 'root') -> Logger: """ 此函数用于从 global_config 中取出对应的配置建立一个相应的 logger @@ -456,41 +514,38 @@ def get_logger(name: str = 'root') -> Logger: the_config = logger_configs['Logger'][name] else: the_config = logger_configs['Logger']['root'] - a_logger = Logger(name=name, - level=the_config['level'], - file_conf=logger_configs['File'][the_config['file']] if 'file' in the_config else None, - colors=logger_configs['Color'][get_key_from_dict(the_config, 'color', 'main_color')], - formats=logger_configs['Formatter']) - return a_logger + return Logger(name=name, + level=the_config['level'], + file_conf=logger_configs['File'][the_config['file']] if 'file' in the_config else None, + colors=logger_configs['Color'][get_key_from_dict(the_config, 'color', 'main_color')], + formats=logger_configs['Formatter']) + + +def test_logger(the_logger: Logger): + the_logger.trace('tracing') + the_logger.fine('some fine!') + the_logger.debug('debugging') + the_logger.info("Hello World!!") + the_logger.warn('warning') + the_logger.error('error haaaa') + the_logger.fatal('oh no') if __name__ == "__main__": - os.chdir('githubs/DR') - # 在这里可以使用 add_kwargs_to_global + os.chdir('D:/githubs/DR') logger = Logger(name="Main", level=NOTSET) - for x in range(5): - logger.trace('tracing') - logger.fine('some fine!') - logger.debug('debugging') - logger.info("Hello World!!") - logger.warn('warning') - logger.error('error haaaa') - logger.fatal('oh no') + logger.info('my name is:', logger.name) a_logger = get_logger('client') a_logger.trace('tracing') - # time.sleep(5) + time.sleep(1.1) a_logger.fine('some fine!') a_logger.debug('debugging') - # time.sleep(5) + time.sleep(1.1) a_logger.info("Hello World!!") a_logger.warn('warning') a_logger.error('error haaaa') a_logger.fatal('oh no') + logger.info('my name is:', logger.name) for x in range(5): - a_logger.trace('tracing') - a_logger.fine('some fine!') - a_logger.debug('debugging') - a_logger.info("Hello World!!") - a_logger.warn('warning') - a_logger.error('error haaaa') - a_logger.fatal('oh no') + test_logger(logger) + test_logger(a_logger) diff --git a/Difficult_Rocket/utils/thread.py b/Difficult_Rocket/utils/thread.py index 1042e3e..a5b55ae 100644 --- a/Difficult_Rocket/utils/thread.py +++ b/Difficult_Rocket/utils/thread.py @@ -16,13 +16,13 @@ import threading from typing import Union from threading import Lock -from Difficult_Rocket import crash +from Difficult_Rocket import DR_option, crash from Difficult_Rocket.exception.threading import LockTimeOutError class Threads(threading.Thread): def run(self): - if crash.record_thread: + if DR_option.record_thread: crash.all_thread.append(self) super().run() @@ -34,27 +34,14 @@ class ThreadLock: self.time_out = time_out def __enter__(self): - # print('enter!') self.lock.acquire(timeout=self.time_out) if not self.lock.locked(): - raise LockTimeOutError('') + raise LockTimeOutError(f'Lock time Out with {self.time_out}') return self def __exit__(self, exc_type, exc_val, exc_tb): if self.lock.locked(): self.lock.release() - if (exc_type is None) and (exc_val is None) and (exc_tb is None): - # 没有出 bug - # print('exit with no error') - return None - else: - # 出 bug 了 - # print(f'exit with error {exc_type} {exc_val}') - return None - - # def __del__(self): - # print('del me!') - # self.__del__() if __name__ == "__main__":