@@ -210,13 +210,28 @@ def _get_conf(self):
210210
211211 @property
212212 def _is_manual_mode (self ) -> bool :
213+ """检查当前题库是否为手动模式或包含手动模式。
214+
215+ Returns:
216+ bool: 如果是手动模式或子题库中包含手动模式返回 True,否则返回 False。
217+ """
213218 return (
214219 getattr (self , 'is_manual' , False ) or
215220 self .__class__ .__name__ == 'TikuManual' or
216221 (self .__class__ .__name__ == 'TikuFallback' and any (getattr (p , 'is_manual' , False ) or p .__class__ .__name__ == 'TikuManual' for p in getattr (self , 'providers' , [])))
217222 )
218223
219224 def query (self ,q_info :dict ) -> Optional [str ]:
225+ """单题搜题方法。
226+
227+ 首先检索本地缓存,缓存未命中则调用 _query 从远程或本地题库获取。
228+
229+ Args:
230+ q_info: 题目信息字典,必须包含 'title' 和 'type'。
231+
232+ Returns:
233+ Optional[str]: 搜到的答案字符串,未搜到或校验失败返回 None。
234+ """
220235 if self .DISABLE :
221236 return None
222237
@@ -250,6 +265,17 @@ def query(self,q_info:dict) -> Optional[str]:
250265 return None
251266
252267 def query_all (self , q_list : list [dict ], query_delay : float = 0.0 ) -> list [Optional [str ]]:
268+ """批量搜题方法。
269+
270+ 优先通过本地缓存过滤,缓存未命中的题目交由 _query_all 批量获取。
271+
272+ Args:
273+ q_list: 题目字典列表。
274+ query_delay: 每道题查询之间的延时(秒)。
275+
276+ Returns:
277+ list[Optional[str]]: 答案列表,与传入的题目列表一一对应。
278+ """
253279 if self .DISABLE :
254280 return [None ] * len (q_list )
255281
@@ -306,15 +332,27 @@ def query_all(self, q_list: list[dict], query_delay: float = 0.0) -> list[Option
306332
307333 @abstractmethod
308334 def _query (self , q_info :dict ) -> Optional [str ]:
309- """
310- 查询接口, 交由自定义题库实现
335+ """查询接口, 交由自定义题库实现
336+
337+ Args:
338+ q_info: 题目信息字典。
339+
340+ Returns:
341+ Optional[str]: 搜到的答案,未搜到返回 None。
311342 """
312343 pass
313344
314345 def _query_all (self , q_list : list [dict ], query_delay : float = 0.0 ) -> list [Optional [str ]]:
315- """
316- 批量查询的实现接口,默认循环调用单个查询 _query。
346+ """批量查询的实现接口,默认循环调用单个查询 _query。
347+
317348 子类若有批量查询或交互需求(如手动模式),可重写此方法。
349+
350+ Args:
351+ q_list: 待搜题列表。
352+ query_delay: 单题请求延时。
353+
354+ Returns:
355+ list[Optional[str]]: 搜到的批量答案列表。
318356 """
319357 results = []
320358 for q in q_list :
@@ -480,6 +518,17 @@ def _query(self, q_info:dict) -> Optional[str]:
480518 return None
481519
482520 def _query_all (self , q_list : list [dict ], query_delay : float = 0.0 ) -> list [Optional [str ]]:
521+ """实现多题库回退的批量查询逻辑。
522+
523+ 根据 providers 配置的顺序,对仍未命中的题目列表依次分配给子题库查询,直至所有题目命中或已无可用题库。
524+
525+ Args:
526+ q_list: 待查询题目列表。
527+ query_delay: 单题请求延时。
528+
529+ Returns:
530+ list[Optional[str]]: 合并后的批量答案列表。
531+ """
483532 results = [None ] * len (q_list )
484533 pending_indices = list (range (len (q_list )))
485534
@@ -1460,16 +1509,27 @@ def __init__(self, config_path: Optional[str] = None) -> None:
14601509
14611510 @staticmethod
14621511 def _extract_option_letters (ans : str ) -> list [str ]:
1512+ """从用户输入的答案中尝试提取纯选项字母。
1513+
1514+ 当且仅当输入的除空白与标点符号外的字符全部为英文字母时才提取,否则返回空列表以指示为文本匹配模式。
1515+
1516+ Args:
1517+ ans: 用户手动输入的原始答案文本。
1518+
1519+ Returns:
1520+ list[str]: 提取出来的大写字母列表,或空列表。
1521+ """
14631522 cleaned = re .sub (r'[\s,,;;、]+' , '' , ans )
14641523 if not cleaned or not re .fullmatch (r'[A-Za-z]+' , cleaned ):
14651524 return []
14661525 return [c .upper () for c in cleaned ]
14671526
14681527 def _init_tiku (self ):
1528+ """根据配置初始化手动模式的参数(输入模式、分隔符等)。"""
14691529 self .default_mode = self ._conf .get ('manual_mode_default' , 'batch' ).strip ().lower ()
14701530 if self .default_mode not in ['batch' , 'single' ]:
14711531 self .default_mode = 'batch'
1472-
1532+
14731533 self .separator = self ._conf .get ('manual_mode_separator' , ';' )
14741534 if self .separator .lower () in ['\\ n' , 'newline' , '换行' ]:
14751535 self .separator = '\n '
@@ -1480,7 +1540,7 @@ def _init_tiku(self):
14801540
14811541 @staticmethod
14821542 def _safe_close_tqdm_bars ():
1483- """安全地清除并关闭所有活动的 tqdm 进度条,防止私有属性变更引发异常 """
1543+ """安全地清除并关闭所有活动的 tqdm 进度条,防止私有属性变更异常。 """
14841544 try :
14851545 from tqdm import tqdm
14861546 if hasattr (tqdm , '_instances' ) and hasattr (tqdm ._instances , '__iter__' ):
@@ -1500,6 +1560,14 @@ def _safe_close_tqdm_bars():
15001560 logger .debug (f"获取/清理 tqdm 实例列表失败: { e } " )
15011561
15021562 def _query (self , q_info : dict ) -> Optional [str ]:
1563+ """手动单题搜题实现。
1564+
1565+ Args:
1566+ q_info: 题目信息字典。
1567+
1568+ Returns:
1569+ Optional[str]: 用户输入的答案字符串,跳过则返回 None。
1570+ """
15031571 # 强行关闭清除所有当前活动的 tqdm 进度条
15041572 self ._safe_close_tqdm_bars ()
15051573
@@ -1509,6 +1577,17 @@ def _query(self, q_info: dict) -> Optional[str]:
15091577 return ans
15101578
15111579 def _query_all (self , q_list : list [dict ], query_delay : float = 0.0 ) -> list [Optional [str ]]:
1580+ """手动批量搜题实现。
1581+
1582+ 根据配置进入批量粘贴流或单题轮询流。
1583+
1584+ Args:
1585+ q_list: 待搜题列表。
1586+ query_delay: 单题延时(此处不生效)。
1587+
1588+ Returns:
1589+ list[Optional[str]]: 用户输入的批量答案列表。
1590+ """
15121591 # 强行关闭清除所有当前活动的 tqdm 进度条
15131592 self ._safe_close_tqdm_bars ()
15141593
@@ -1523,6 +1602,7 @@ def _query_all(self, q_list: list[dict], query_delay: float = 0.0) -> list[Optio
15231602
15241603 @staticmethod
15251604 def _get_type_display (type_str : str ) -> str :
1605+ """获取题目类型的中文友好名称。"""
15261606 type_map = {
15271607 'single' : '单选题' ,
15281608 'multiple' : '多选题' ,
0 commit comments