A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

本帖最后由 逆风TO 于 2019-4-23 13:51 编辑

python 自动生成文档
python 自动生成文档
一、配置文档
二、protobuf
三、代码
python 自动生成文档
一、配置文档
register.temeprate
# Datetime: ${DATETIME}

from proto import ${FILENAME}_pb2
from proto import xCmd_pb2


def register_${WRITEFILE}(pbmap):
    pbmap.register_command(
            xCmd_pb2.${PROTTOCMD},
            ${FILENAME}_pb2.${PARAMNAME}Param)  # ${NUMBER}

cmd.temperate
   pbmap.register_descriptor(
           xCmd_pb2.${PROTTOCMD},
           ${FILENAME}_pb2.${CMD})  # ${NUMBER}
</securityRealm>

二、protobuf
// scene -> client : puzzle item ntf
message PuzzleItemNtf
{
  optional Command cmd = 1 [ default = PUZZLE_PROTOCMD ];
  optional PuzzleParam param = 2 [ default = PUZZLEPARAM_ITEMNTF ];

  repeated PuzzleItem items = 3;
}

// client <-> scene : get reward
message ActivePuzzleCmd
{
  optional Command cmd = 1 [ default = PUZZLE_PROTOCMD ];
  optional PuzzleParam param = 2 [ default = PUZZLEPARAM_ACTIVIEPUZZLE ];

  optional uint32 actid = 3 [ default = 0 ];
  optional uint32 puzzleid = 4 [ default = 0 ];
}

三、代码
# Author: Allan
# Datetime: 2019-03-15
# 遍历 proto 目录下使用文件,自动在 pbmap 目录下生成相应文件

import re
import os
from datetime import datetime
from string import Template


class AutoCreateFile:

    def __init__(self):
        self.file_path = r'./proto/{}.proto'
        self.command, self.xCmds = self.get_params('xCmd.proto')
        self.write_file = ''

    def generate(self, filename):
        """
        自动生成 pbmap 文件
        :param filename: protobuf 文件
        :return: None
        """
        flag = False  # 是否存在(PROTOCMD)命令
        lines = []
        current_datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        file_path = self.file_path.format(filename)
        cmds_detail, count = self.get_commands_detail(file_path)
        if count > 1:
            print('{} 存在 {} 个 PROTOCMD 命令'.format(filename, count))

        if cmds_detail:
            if filename.endswith('Cmd'):
                self.write_file = filename.split('Cmd')[0]
            else:
                self.write_file = filename
            number = self.get_protocmd_number(cmds_detail[0]['proto_cmd'])
            with open(r'register.temperate', 'r') as f:
                temp_param = Template(f.read())
                lines.append(temp_param.substitute(
                    DATETIME=current_datetime,
                    WRITEFILE=self.write_file,
                    FILENAME=filename,
                    PARAMNAME=cmds_detail[0]['param_name'],
                    PROTTOCMD=cmds_detail[0]['proto_cmd'],
                    NUMBER=number))

            with open(r'cmd.temperate', 'r') as f:
                cmd_params = Template(f.read())
                for command in cmds_detail:
                    lines.append(cmd_params.substitute(
                        FILENAME=filename,
                        PROTTOCMD=command['proto_cmd'],
                        PARAM=command['param'],
                        CMD=command['cmd_name']))
                    flag = True

        if flag:
            # 如果有命令(PROTOCMD),生成 pbmap 文件
            self.write_pbmap(lines)

    def get_params(self, filename):
        """
        获取 protobuf 文件中的参数
        :param filename: protobuf 文件
        :return: param_name, params
        """
        with open(filename, 'r') as f:
            params = []
            lines = f.readlines()
            param_name = re.search(r'^enum .*', ''.join(lines), re.M)
            param_name = param_name.group().split()[1].split('Param')[0]
            flag = False
            for param in lines:
                # 遍历第一个enum,并过滤空行和注释行
                if '{' in param:
                    flag = True
                    continue
                elif "}" in param:
                    break
                if flag and param != '\n' and not param.startswith('//'):
                    params.append(param.strip().split(';')[0])
        return param_name, params

    def get_protocmd_number(self, proto_param):
        for param in self.xCmds:
            if proto_param in param:
                number = param.replace(' ', '').split('=')[1]
                return number

    def get_commands_detail(self, filename):
        """
        获取 cmd 详细信息
        :param filename: protobuf 文件
        :param param: CmdParam (例如,AchiveParam)
        :return: cmds_detail: [proto_cmd, cmd_name, param_name, param]
                 count: 大于1,则文件存在重复的PROTOCMD
        """
        with open(filename, 'r') as f:
            count = 0
            cmds_detail = []
            temp_proto_cmd = ""
            lines = f.readlines()
            for i in range(len(lines)):
                if 'PROTOCMD' in lines and '//' not in lines:
                    cmd_detail = {'proto_cmd': '', 'cmd_name': '', 'param_name': '', 'param': ''}
                    proto_cmd = lines.replace(' ', '').split(']')[0].split('=')[-1]
                    cmd_name = lines[i-2].split()[1]
                    param = lines[i+1].replace(' ', '').split(']')[0].split('=')[-1]
                    if 'Param' not in lines[i+1]:
                        continue
                    param_name = lines[i+1].strip().split()[1]
                    cmd_detail['proto_cmd'] = proto_cmd
                    if temp_proto_cmd != proto_cmd:
                        "记录重复的PROTOCMD文件"
                        temp_proto_cmd = proto_cmd
                        count += 1
                    cmd_detail['cmd_name'] = cmd_name
                    cmd_detail['param'] = param
                    cmd_detail['param_name'] = param_name
                    cmds_detail.append(cmd_detail)
            return cmds_detail, count

    def write_pbmap(self, info):
        """
        写入信息到 pbmap 文件
        :param info: 信息
        :return: None
        """
        filename = r'./pbmap/{}.py'.format(self.write_file)
        with open(filename, 'w') as f:
            f.writelines(info)

    def read_directory(self, path):
        """
        遍历目录,查找使用文件名
        :param path: 目标目录
        :return: 所有文件名
        """
        results = []
        path = os.listdir(path)
        for i, item in enumerate(path):
            if item.endswith('.proto'):
                results.append(item)
        return results


if __name__ == '__main__':
    acf = AutoCreateFile()
    res = acf.read_directory(path=r'./proto')
    for result in res:
        path = result.split('.')[0]
        acf.generate(path)


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马