Example #1
0
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,
    )
Example #2
0
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
Example #3
0
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}文件")
Example #4
0
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
Example #5
0
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