Skip to content

Commit 0ec83b1

Browse files
committed
dir_rule重构
1 parent 398e1ea commit 0ec83b1

1 file changed

Lines changed: 45 additions & 73 deletions

File tree

src/jmcomic/jm_option.py

Lines changed: 45 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -58,56 +58,40 @@ def enable_client_cache_on_condition(cls,
5858

5959

6060
class DirRule:
61-
rule_sample = [
62-
# 根目录 / Album-id / Photo-序号 /
63-
'Bd_Aid_Pindex', # 禁漫网站的默认下载方式
64-
# 根目录 / Album-作者 / Album-标题 / Photo-序号 /
65-
'Bd_Aauthor_Atitle_Pindex',
66-
# 根目录 / Photo-序号&标题 /
67-
'Bd_Pindextitle',
68-
# 根目录 / Photo-自定义类属性 /
69-
'Bd_Aauthor_Atitle_Pcustomfield',
70-
# 需要替换JmModuleConfig.CLASS_ALBUM / CLASS_PHOTO才能让自定义属性生效
71-
]
72-
73-
Detail = Union[JmAlbumDetail, JmPhotoDetail, None]
74-
RuleFunc = Callable
75-
RuleSolver = Tuple[str, RuleFunc, str]
76-
RuleSolverList = List[RuleSolver]
7761

7862
def __init__(self, rule: str, base_dir=None):
7963
base_dir = JmcomicText.parse_to_abspath(base_dir)
8064
self.base_dir = base_dir
8165
self.rule_dsl = rule
82-
self.solver_list = self.get_role_solver_list(rule, base_dir)
66+
self.parser_list: List[Tuple[str, Callable]] = self.get_rule_solver_list(rule)
8367

8468
def decide_image_save_dir(self,
8569
album: JmAlbumDetail,
8670
photo: JmPhotoDetail,
8771
) -> str:
8872
path_ls = []
89-
for solver in self.solver_list:
73+
for rule, parser in self.parser_list:
9074
try:
91-
ret = self.apply_rule_solver(album, photo, solver)
75+
path = parser(album, photo, rule)
9276
except BaseException as e:
9377
# noinspection PyUnboundLocalVariable
94-
jm_log('dir_rule', f'路径规则"{solver[2]}"的解析出错: {e}, album={album}, photo={photo}')
78+
jm_log('dir_rule', f'路径规则"{rule}"的解析出错: {e}, album={album}, photo={photo}')
9579
raise e
80+
if parser != self.parse_bd_rule:
81+
path = fix_windir_name(str(path)).strip()
9682

97-
path_ls.append(str(ret))
83+
path_ls.append(path)
9884

9985
return fix_filepath('/'.join(path_ls), is_dir=True)
10086

10187
def decide_album_root_dir(self, album: JmAlbumDetail) -> str:
10288
path_ls = []
103-
for solver in self.solver_list:
104-
key, _, rule = solver
105-
106-
if key != 'Bd' and key != 'A':
89+
for rule, parser in self.parser_list:
90+
if rule != 'Bd' or not rule.startswith('A'):
10791
continue
10892

10993
try:
110-
ret = self.apply_rule_solver(album, None, solver)
94+
ret = parser(album, None, parser)
11195
except BaseException as e:
11296
# noinspection PyUnboundLocalVariable
11397
jm_log('dir_rule', f'路径规则"{rule}"的解析出错: {e}, album={album}')
@@ -117,30 +101,49 @@ def decide_album_root_dir(self, album: JmAlbumDetail) -> str:
117101

118102
return fix_filepath('/'.join(path_ls), is_dir=True)
119103

120-
def get_role_solver_list(self, rule_dsl: str, base_dir: str) -> RuleSolverList:
104+
def get_rule_solver_list(self, rule_dsl: str):
121105
"""
122106
解析下载路径dsl,得到一个路径规则解析列表
123107
"""
124108

125109
rule_list = self.split_rule_dsl(rule_dsl)
126-
solver_ls: List[DirRule.RuleSolver] = []
110+
parser_list: list = []
127111

128112
for rule in rule_list:
129113
rule = rule.strip()
130114
if rule == 'Bd':
131-
solver_ls.append(('Bd', lambda _: base_dir, 'Bd'))
115+
parser_list.append((rule, self.parse_bd_rule))
132116
continue
133117

134-
rule_solver = self.get_rule_solver(rule)
135-
if rule_solver is None:
118+
parser = self.get_rule_parser(rule)
119+
if parser is None:
136120
ExceptionTool.raises(f'不支持的dsl: "{rule}" in "{rule_dsl}"')
137121

138-
solver_ls.append(rule_solver)
122+
parser_list.append((rule, parser))
123+
124+
return parser_list
125+
126+
# noinspection PyUnusedLocal
127+
def parse_bd_rule(self, album, photo, rule):
128+
return self.base_dir
129+
130+
@classmethod
131+
def parse_f_string_rule(cls, album, photo, rule: str):
132+
properties = {}
133+
if photo:
134+
properties.update(photo.getproperties())
135+
if album:
136+
properties.update(photo.getproperties())
139137

140-
return solver_ls
138+
return rule.format(properties)
139+
140+
@classmethod
141+
def parse_detail_rule(cls, album, photo, rule: str):
142+
detail = album if rule.startswith('A') else photo
143+
return str(DetailEntity.get_dirname(detail, rule[1:]))
141144

142145
# noinspection PyMethodMayBeStatic
143-
def split_rule_dsl(self, rule_dsl: str) -> List[str]:
146+
def split_rule_dsl(self, rule_dsl: str):
144147
if rule_dsl == 'Bd':
145148
return [rule_dsl]
146149

@@ -153,50 +156,19 @@ def split_rule_dsl(self, rule_dsl: str) -> List[str]:
153156
ExceptionTool.raises(f'不支持的rule配置: "{rule_dsl}"')
154157

155158
@classmethod
156-
def get_rule_solver(cls, rule: str) -> Optional[RuleSolver]:
159+
def get_rule_parser(cls, rule: str):
157160
if '{' in rule:
158-
def format_path(album, photo):
159-
return fix_windir_name(rule.format(**album.get_properties_dict(), **photo.get_properties_dict())).strip()
160-
161-
return 'F', format_path, rule
161+
return cls.parse_f_string_rule
162162

163-
# 检查dsl
164-
if not rule.startswith(('A', 'P')):
165-
return None
163+
if rule.startswith(('A', 'P')):
164+
return cls.parse_detail_rule
166165

167-
def solve_func(detail):
168-
return fix_windir_name(str(DetailEntity.get_dirname(detail, rule[1:]))).strip()
169-
170-
return rule[0], solve_func, rule
171-
172-
@classmethod
173-
def apply_rule_solver(cls, album, photo, rule_solver: RuleSolver) -> str:
174-
"""
175-
应用规则解析器(RuleSolver)
176-
177-
:param album: JmAlbumDetail
178-
:param photo: JmPhotoDetail
179-
:param rule_solver: Ptitle
180-
:returns: photo.title
181-
"""
182-
183-
def choose_detail(key):
184-
if key == 'Bd':
185-
return None,
186-
if key == 'A':
187-
return album,
188-
if key == 'P':
189-
return photo,
190-
if key == 'F':
191-
return album, photo
192-
193-
key, func, _ = rule_solver
194-
detail = choose_detail(key)
195-
return func(*detail)
166+
ExceptionTool.raises(f'不支持的rule配置: "{rule}"')
196167

197168
@classmethod
198169
def apply_rule_directly(cls, album, photo, rule: str) -> str:
199-
return cls.apply_rule_solver(album, photo, cls.get_rule_solver(rule))
170+
# noinspection PyArgumentList
171+
return cls.get_rule_parser(rule)(album, photo, rule)
200172

201173

202174
class JmOption:
@@ -471,7 +443,7 @@ def update_cookies(self, cookies: dict):
471443
orig_cookies.update(cookies)
472444
metadata['cookies'] = orig_cookies
473445

474-
# noinspection PyMethodMayBeStatic
446+
# noinspection PyMethodMayBeStatic,PyTypeChecker
475447
def decide_client_domain(self, client_key: str) -> List[str]:
476448
def is_client_type(ctype) -> bool:
477449
return self.client_key_is_given_type(client_key, ctype)

0 commit comments

Comments
 (0)