def cache_class_handler(class_handler: Callable, handler_name: str): # 不要每次都创建实例,on/register监听器新增时建立一次保存起来即可 class_handler_instance = class_handler() # groupHandler可能有多个装饰器,比如register, withCommand # 先解析为与装饰器名称相关的缓存至groupMeta, # 解析完所有装饰器之后,再生成classHandlers.groupCache中的缓存 # 生成缓存时,确保register的存在,不然报错(withCommand也可以向group中推送meta信息) # 这才是真正的meta,全局保存class和对应的meta,而不是绑定到class上,可能会涉及到bound和unbound的问题 event_handlers: Dict[str, Callable] = {} # 初始化时,遍历生成缓存,不要每次接收到消息都去遍历 for method in get_own_methods(class_handler_instance): method_name = method.__name__ # todo 多protocol合并的事件 # if not is_valid_group_method(method_name): # # if is_valid_friend_method(method.__name__): # raise EventHandlerDefineError(f"") # if not is_valid_event_handler(class_handler, method, method_name): # raise EventHandlerDefineError(f"") event_handlers[method_name] = method class_handler_mapping[handler_name] = ClassHandlerCache( class_instance=class_handler_instance, event_handlers=event_handlers, )
def is_valid_class_handler(class_handler: object): for method in get_own_methods(class_handler): method_name = method.__name__ is_handler_method_name_valid(method_name) is_handler_method_args_valid(class_handler, method, method_name) return True
def gen_api_markdown(target_api_class: Any, output_file_path: str, extra_head: str = ""): md_file = MdUtils(file_name=output_file_path) if extra_head: md_file.write(extra_head) md_file.new_header(level=1, title="") for method in get_own_methods(target_api_class): method_name = method.__name__ md_file.new_header(level=2, title=method_name) docstring = method.__doc__ if docstring: md_file.write(f"\n{method.__doc__}\n") parameter_table = ["参数名称", "类型", "默认值"] for parameter in inspect.signature(method).parameters.values(): if parameter.name == "self": continue row = [parameter.name] if isinstance(parameter.annotation, str): row.append(parameter.annotation) else: if get_origin(parameter.annotation) is Union: # group_msg = group_message continue row.append(parameter.annotation.__name__) if parameter.default == inspect._empty: row.append("无") else: if parameter.default: row.append(parameter.default) else: row.append("无") parameter_table.extend(row) # debug(parameter_table) # md_file.new_line() if len(parameter_table) > 3: md_file.new_table( columns=3, rows=int(len(parameter_table) / 3), text=parameter_table, text_align="center", ) md_file.create_md_file() print(f"成功生成{output_file_path}文件")
def cache_class_command(class_command: Callable, command_name: str): # 多个group handler,相同command的处理(解析所有指令和groupId,重新生成缓存) # 同一个commandClass,就实例化一次 # if lifecycle_name not in get_own_methods(): class_command_instance = class_command() command_method_mapping = {} for method in get_own_methods(class_command_instance): method_name = method.__name__ patterns: List[Tuple[str, T_PatternArg]] = [] compressed_patterns = [] if method_name not in LIFECYCLE_WITHOUT_PATTERNS: signature = inspect.signature(method) for arg_name, p in signature.parameters.items(): if p.default == "PatternArg": annotation = p.annotation if annotation not in runtime_pattern_arg_types: raise InitializationError(f"仅支持str, bool, int, float和所有消息类型") # 未具体指定类型(int, float, bool)的Text按照str处理 patterns.append( (arg_name, annotation if annotation != Text else str) ) # debug(patterns) compressed_patterns = merge_text_of_patterns(patterns) # debug(compressed_patterns) command_method_mapping[method_name] = CommandMethodCache( method=method, patterns=patterns, compressed_patterns=compressed_patterns, ) class_command_mapping[command_name] = ClassCommandCache( class_instance=class_command_instance, command_method_mapping=command_method_mapping, ) command_config: CommandConfig = getattr(class_command, COMMAND_CONFIG) class_command_config_mapping[command_name]["default"] = command_config
def is_valid_class_command(class_command: Any): source_file_name = inspect.getsourcefile(class_command) class_command_name = class_command.__name__ common_prefix = f"\n{source_file_name} 文件中的指令 {class_command_name} 的" methods = list(get_own_methods(class_command)) method_names = [method.__name__ for method in methods] if not "initial" in method_names: raise InitializationError("指令必须定义initial方法作为入口") for method in methods: method_name = method.__name__ is_command_method_args_valid(method, method_name, common_prefix) is_command_method_return_valid(method, method_name, method_names, common_prefix) return True