-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b1df7f5
commit 22873d1
Showing
8 changed files
with
657 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
''' | ||
该模块用于格式化代码 | ||
''' | ||
from typing import Dict | ||
from .debug import log_warning | ||
from .module_manager import invoke_script | ||
|
||
def format_code(code:str,card:Dict[str,object], | ||
project,children_code:str='',stack:list = None): | ||
'''格式化代码''' | ||
if not stack: | ||
stack = [] | ||
matches = findall_placeholders(code) | ||
for match in matches: | ||
#LogDebug(str(match)) | ||
qurey_tuple = split_args(match) | ||
attr_name = qurey_tuple[0] | ||
if attr_name in stack: | ||
log_warning(f'[Formatter] 检测到循环调用: {stack}') | ||
return code | ||
for item in qurey_tuple[1:]: | ||
# 格式化参数 | ||
item = format_code(code=item,card=card,project=project, | ||
children_code=children_code,stack=stack) | ||
if attr_name.startswith('$') or attr_name.startswith('@'): | ||
replacement = invoke_script(script_name=qurey_tuple[0][1:], | ||
project=project,card=card,args=qurey_tuple[1:], | ||
children_code=children_code) | ||
elif attr_name in card: | ||
replacement = str(card[attr_name]) | ||
else: | ||
if len(qurey_tuple) >= 1: | ||
replacement = qurey_tuple[-1] | ||
else: | ||
log_warning(f'[Formatter] 访问了不存在的属性,并且没有设定默认值: {attr_name}') | ||
continue | ||
stack.append(attr_name) | ||
try: | ||
replacement = format_code(replacement,card,project,children_code,stack) | ||
finally: | ||
stack.pop() | ||
code = code.replace(f'${{{match}}}',replacement,1) | ||
return code | ||
|
||
def split_args(string:str): | ||
'''分离参数''' | ||
args = [] | ||
in_qoute = False | ||
pare_deepth = 0 | ||
buffer = '' | ||
for c in string: | ||
buffer += c | ||
if in_qoute: | ||
if c == '"': | ||
in_qoute = False | ||
else: | ||
if c == '{': | ||
pare_deepth += 1 | ||
if pare_deepth > 0: | ||
if c == '}': | ||
pare_deepth -= 1 | ||
else: | ||
match c: | ||
case '|': | ||
args.append(buffer[:-1]) | ||
buffer = '' | ||
case '"': | ||
in_qoute = True | ||
args.append(buffer) | ||
return args | ||
|
||
def findall_placeholders(string:str): | ||
'''寻找全部占位符''' | ||
if not string: | ||
return [] | ||
placeholders = [] | ||
pare_deepth = 0 | ||
sp_mode = False | ||
buffer = '' | ||
for c in string: | ||
if pare_deepth > 0: | ||
if c == '}': | ||
pare_deepth -= 1 | ||
if pare_deepth == 0: | ||
placeholders.append(buffer) | ||
buffer = '' | ||
else: | ||
buffer += c | ||
else: | ||
buffer += c | ||
if c == '{' and (sp_mode or pare_deepth > 0): | ||
pare_deepth += 1 | ||
if c == '$': | ||
sp_mode = True | ||
else: | ||
sp_mode = False | ||
return placeholders |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
''' | ||
该模块用于输出调试与日志信息 | ||
''' | ||
|
||
TAB_TEXT = ' ' | ||
CONSOLE_CLEAR = '\033[0m' | ||
CONSOLE_BLACK = '\033[30m' | ||
CONSOLE_RED = '\033[31m' | ||
CONSOLE_GREEN = '\033[32m' | ||
CONSOLE_YELLOW = '\033[33m' | ||
CONSOLE_BLUE = '\033[34m' | ||
CONSOLE_MAGENTA = '\033[35m' | ||
CONSOLE_CYAN = '\033[36m' | ||
CONSOLE_WHITE = '\033[37m' | ||
|
||
class Logger: | ||
'''日志记录器''' | ||
def __init__(self,source_name): | ||
self.source = source_name | ||
|
||
def info(self,infomation:str): | ||
'''输出信息''' | ||
print(f'{CONSOLE_BLUE}[INFO]{CONSOLE_CLEAR}[{self.source}] {infomation}') | ||
|
||
def warning(self,infomation:str): | ||
'''输出警告''' | ||
print(f'{CONSOLE_YELLOW}[WARNING]{CONSOLE_CLEAR}[{self.source}] {infomation}') | ||
|
||
def debug(self,infomation:str): | ||
'''输出调试信息''' | ||
print(f'{CONSOLE_GREEN}[DEBUG]{CONSOLE_CLEAR}[{self.source}] {infomation}') | ||
|
||
def error(self,infomation:str): | ||
'''输出错误信息''' | ||
print(f'{CONSOLE_RED}[ERROR][{self.source}] {infomation}') | ||
return infomation | ||
|
||
def fatal(self,infomation:str): | ||
'''输出致命错误信息''' | ||
print(f'{CONSOLE_RED}[FATAL][{self.source}] {infomation}') | ||
return infomation | ||
|
||
def log_info(infomation:str): | ||
'''输出信息''' | ||
print(f'{CONSOLE_BLUE}[INFO]{CONSOLE_CLEAR}{infomation}') | ||
|
||
def log_warning(infomation:str): | ||
'''输出警告''' | ||
print(f'{CONSOLE_YELLOW}[WARNING]{CONSOLE_CLEAR}{infomation}') | ||
|
||
def log_debug(infomation:str): | ||
'''输出调试信息''' | ||
print(f'{CONSOLE_GREEN}[DEBUG]{CONSOLE_CLEAR}{infomation}') | ||
|
||
def log_error(infomation:str): | ||
'''输出错误信息''' | ||
print(f'{CONSOLE_RED}[ERROR]{infomation}') | ||
return infomation | ||
|
||
def log_fatal(infomation:str): | ||
'''输出致命错误信息''' | ||
print(f'{CONSOLE_RED}[FATAL]{infomation}') | ||
return infomation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
''' | ||
编码与反编码字符串模块 | ||
''' | ||
esc_chars = { | ||
'&':'&', | ||
'<':'<', | ||
'>':'>', | ||
'"':'"', | ||
"'":''' | ||
} | ||
|
||
def decode_escape(string:str): | ||
'''反编码转义字符''' | ||
for key,value in esc_chars.items(): | ||
string = string.replace(value,key) | ||
return string | ||
|
||
def encode_escape(string:str): | ||
'''编码转义字符''' | ||
for key,value in esc_chars.items(): | ||
string = string.replace(key,value) | ||
return string |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
''' | ||
该模块内存放了卡片库类 | ||
''' | ||
import os | ||
from typing import Tuple | ||
from .io import scan_dire,scan_sub_dire | ||
from .debug import Logger | ||
from .i18n import locale as t | ||
|
||
logger = Logger('Library') | ||
class Library: | ||
'''卡片库类''' | ||
def __init__(self,data:dict): | ||
self.name= data['name'] | ||
logger.info(t('library.load',name=self.name)) | ||
self.fill = data.get('fill',{}) | ||
self.cover = data.get('cover',{}) | ||
self.card_mapping = {} # 卡片索引 | ||
self.libs_mapping = {} # 子库索引 | ||
self.sub_libraries = {} # 子库 | ||
self.cards = {} | ||
self.location = os.path.dirname(data['file_path']) | ||
for file_tuple in scan_dire(self.location,r'^(?!^__LIBRARY__.yml$).*$'): # 库所拥有的卡片 | ||
self.add_card_from_file_tuple(file_tuple) | ||
self.add_sub_libraries(scan_sub_dire(self.location,'__LIBRARY__.yml')) # 遍历添加子库 | ||
|
||
@classmethod | ||
def decorate_card(cls,card,fill,cover): | ||
'''用 fill 和 cover 修饰卡片''' | ||
if fill: | ||
cloned_fill = fill.copy() | ||
else: | ||
cloned_fill = {} | ||
if cover: | ||
card.update(cover) | ||
cloned_fill.update(card) | ||
return cloned_fill | ||
|
||
def __decorate_card(self,card): | ||
'''用本卡片库的 fill 和 cover 修饰卡片''' | ||
return self.decorate_card(card,self.fill,self.cover) | ||
|
||
def __get_card_decoless(self,card_ref:str,is_original:bool): | ||
'''获取未经 fill 和 cover 的卡片''' | ||
if card_ref in self.cards: | ||
return self.cards[card_ref] | ||
if ':' in card_ref: | ||
libname,cardname = card_ref.split(':',2) | ||
if libname == self.name: | ||
card_ref = cardname | ||
else: | ||
return self.get_card_from_lib_mapping(libname,cardname,is_original) | ||
return self.get_card_from_card_mapping(card_ref,is_original) | ||
|
||
def get_card(self,card_ref:str,is_original:bool): | ||
'''获取卡片''' | ||
target = self.__get_card_decoless(card_ref,is_original) | ||
if is_original: | ||
return target | ||
else: | ||
return self.__decorate_card(target) | ||
|
||
def get_card_from_card_mapping(self,card_ref:str,is_original:bool): | ||
'''通过库内的卡片映射获取卡片''' | ||
if card_ref in self.cards: | ||
return self.cards[card_ref].copy() | ||
elif card_ref in self.card_mapping: | ||
return self.card_mapping[card_ref].get_card(card_ref,is_original) | ||
else: | ||
raise KeyError(logger.error(f'[Library] Cannot find card "{card_ref}"')) | ||
|
||
def get_card_from_lib_mapping(self,lib_name,card_ref,is_original): | ||
'''通过库内的库映射获取卡片''' | ||
if lib_name == 'T': | ||
return {'templates':[card_ref]} | ||
if lib_name in self.libs_mapping: | ||
return self.libs_mapping[lib_name].get_card(card_ref,is_original) | ||
else: | ||
raise KeyError(logger.error(f'[Library] Cannot find library "{card_ref}"')) | ||
|
||
def add_card_from_file_tuple(self,file_info_tuple:Tuple[object,str,str]): | ||
'''通过文件元组添加卡片''' | ||
data, filename, exten = file_info_tuple | ||
name = filename | ||
if isinstance(data,dict): | ||
if 'name' in data: | ||
name = data['name'] | ||
self.cards[name] = data | ||
else: | ||
self.cards[name] = {'data':data } | ||
self.cards[name].update({'data':data,'file_name':filename,'file_exten':exten, | ||
'card_id':f'{self.name}:{name}','card_lib':self.name, | ||
'card_name':name}) | ||
|
||
def add_sub_libraries(self,yamldata): | ||
'''增加子库''' | ||
def add_sub_library(self,yamldata): | ||
sublib = Library(yamldata) | ||
self.sub_libraries.update({sublib.name:sublib}) | ||
# 将子库的卡片索引加入父库并映射到该子库 | ||
for cardname in sublib.card_mapping: | ||
self.card_mapping.update({cardname:sublib}) | ||
# 将子库的所有卡片加入父库并映射到该子库 | ||
for cardname in sublib.cards: | ||
self.card_mapping.update({cardname:sublib}) | ||
# 将子库的子库引加入父库并映射到该子库 | ||
for libname in sublib.libs_mapping: | ||
self.libs_mapping.update({libname:sublib}) | ||
# 将该子库加入父库的子库索引 | ||
self.libs_mapping.update({sublib.name:sublib}) | ||
if isinstance(yamldata,list): | ||
for data in yamldata: | ||
self.add_sub_libraries(data) | ||
elif isinstance(yamldata,tuple): | ||
add_sub_library(self,yamldata[0]) | ||
else: | ||
add_sub_library(self,yamldata) | ||
# DEV NOTICE 如果映射的内存占用太大了就将每一个卡片和每一个子库的路径压成栈,交给根库来管理 | ||
|
||
def get_all_cards(self): | ||
'''获取该库的所有卡片''' | ||
result = [self.__decorate_card(card) for card in self.cards.values()] | ||
for lib in self.sub_libraries.values(): | ||
result += [self.__decorate_card(card) for card in lib.get_all_cards()] | ||
return result |
Oops, something went wrong.