Package: config-server
参数网络配置系统使用手册声明版权所有 © 2023 成都研码帮信息技术有限公司。所有权利保留。未经明确的书面授权，不得用于商业用途。引言定义系统名称：参数网络配置系统（以下简称“本系统”）。编写目的本手册较详细地介绍了本系统的应用程序接口与使用方法，用户通过查看本手册，可以了解如何使用本系统。系统介绍系统简介在程序设计的功能中，随着版本的迭代，程序的功能会逐渐累计；功能越多的程序，一般越需要用户自行选择启用哪些功能，并在一定程度上可以决定程序执行的流程等，这样的过程可以称为对程序进行“配置”。不同的程序面向不同的使用人群，不同的使用人群也会有不同的配置方式。例如，没有程序设计基础的普通用户更偏向于使用携带用户操作界面的配置页面，部分具有程序设计基础的用户更偏向于使用命令行参数输入、载入配置文件等配置方式，部分开发者更偏向于使用软件开发工具包来按照需求定制程序配置方案。另一方面，随着程序功能增多，配置参数之间极可能出现耦合和约束关系。由于目前行业内尚未有公开的、成熟的、针对携带复杂参数的程序的软件开发工具，因此开发本系统以填补行业空缺，为复杂配置参数的场景提供解决方案。由于 python 语言有着“胶水语言”的特性，能很好地与其他编程语言（如 C，Java，Fortran 等）编写的程序进行交互，并且它的学习门槛低，应用范围广， 本系统形成了一套 python 语言的软件开发工具包。本系统将复杂参数的关系以树状图进行整理，以 yaml 格式的配置文件为标准，开发者可以通过该系统定制包含复杂约束关系的参数配置系统，可以生成网页端的配置页面、命令行操作接口、配置文件接口、网站后台接口等多种接入方案，可满足不同用户的使用习惯。系统流程图%%{init: {
'theme': 'base',
'themeVariables': {
'fontSize': '24px',
'fontFamily': "SimSun, serif",
'background': '#efefef',
'primaryColor': '#fff',
'primaryTextColor': '#000',
'primaryBorderColor': '#000',
'lineColor': '#000',
'secondaryColor': '#000',
'tertiaryColor': '#000'}}}%%
flowchart TB
    a(开始)
    b[通过思维导图整理参数结构]
    c[配置python环境]
    d[载入本系统]
    e[定义参数结点]
    f[运行程序]
    g(结束)
    a --> b --> c --> d --> e --> f --> g设计概念通过思维导图的整理后的参数结构是树状的，而树状的数据可分为根节点、子节点、叶子节点，如下图所示：mindmap
  root((根节点))
    叶子节点
    子节点
      叶子节点
      叶子节点
      子节点
        叶子节点
        叶子节点
    子节点
      叶子节点
      叶子节点在配置文件中，"根节点"对应配置文件本身，"子节点"对应若干个参数所在的分组，"叶子节点"对应某个参数，如下图所示：mindmap
  root((配置文件))
    一级参数
    一级分组
      二级参数
      二级参数
      二级分组
        三级参数
        三级参数
    一级分组
      二级参数
      二级参数在参数说明文档应以章节号的形式体现参数的分组结果，在参数说明文档的每小节对应某个分组或参数。例如，以下是参数说明文档目录的示例：1. 一级参数
2. 一级分组
    2.1 二级参数
    2.2 二级参数
    2.3 二级分组
        2.3.1 三级参数
        2.3.2 三级参数
3. 一级分组
    3.1 二级参数
    3.2 二级参数快速入门本小节中将通过构建一个用户信息管理程序为案例，详细讲解如何使用本系统。参数结构mindmap
  UserSystem((用户系统))
    UserName))用户名((
    Gender))性别((
    Age))年龄((
    AuthInfo[账号信息（多选一）]
      EmailLogin[邮箱登录]
        Email))邮箱地址((
        Password))密码((
      PhoneLogin[手机登录]
        Phone))手机号码((
        Password))密码((参数文档用户名用户名是用户在系统中的唯一标识符。性别可选“男”、“女”或“保密”，默认值为“保密”。年龄选项说明0-18岁未成年人19-44岁青年人45-59岁中年人60岁以上老人账号信息为了方便和安全考虑，系统提供了两种不同的登录方式供用户选择（多选一）：邮箱登录：若使用该方式，用户需要填写：邮箱地址： 用户的有效电子邮箱地址；密码：与邮箱地址关联的密码。手机号登录： 若使用该方式，用户需要填写：手机号码： 用户的有效手机号码；密码：与手机号码关联的密码。程序定义fromtypingimportLiteralfromenumimportEnumimportpydantic# 支持Pydantic内置的类型标注fromconfig_serverimport(set_title,set_doc,add_union_field,ConfigLeaf,ConfigNode,)@set_title("用户名")# 通过装饰器设置标题@set_doc("用户名是用户在系统中的唯一标识符")# 通过装饰器设置字段的详细说明classUserName(ConfigLeaf):root:str# 只是做了类型标注，但没有赋值，表示该字段为必填字段@set_title("性别")classGender(ConfigLeaf):root:Literal["男","女","保密"]="保密"# 直接赋值，表示默认值为“保密”@set_title("年龄")@set_doc("""|   选项   |   说明   || :------: | :-----: ||  0-18岁  | 未成年人 || 19-44岁  |  青年人  || 45-59岁  |  中年人  || 60岁以上  |   老人   |""")classAge(ConfigLeaf):# 当选项较多时，也通过枚举类来定义可选项classAgeEnum(Enum):young="0-18岁"middle="19-44岁"old="45-59岁"elderly="60岁以上"root:AgeEnum=AgeEnum.middle.value# 在全局作用域中定义（叶）子节点，以便复用（例如，手机/邮箱登录都需要定义密码）@set_title("密码")classPassword(ConfigLeaf):root:str# 通过重写`verify_constraints`方法来实现自定义的约束，# 本方法会在实例化时自动调用；若验证不通过，请抛出异常；# 如果需要表示跨节点的约束条件，请在其最近的共同父节点中定义。defverify_constraints(self)->None:iflen(self.root)<8:raiseValueError("密码长度不能小于8位")@set_title("邮箱登录")classEmailLogin(ConfigNode):@set_title("邮箱地址")classEmail(ConfigLeaf):# 可通过pydantic.constr来添加正则表达式约束root:pydantic.constr(pattern=r"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$")address:Emailpassword:Password@set_title("手机登录")classPhoneLogin(ConfigNode):@set_title("手机号码")classPhone(ConfigLeaf):root:strphone:Phonepassword:Password@set_title("注册信息")@set_doc("""提供了两种不同的登录方式供用户选择：| 登录方式 |      说明          || :---:  | :----------------: ||  邮箱   | 用户可以使用邮箱登录  ||  手机   | 用户可以使用手机号登录 |""")# 详细说明支持markdown语法@add_union_field(# 通过装饰器添加多类型字段（多选一）field_name="root",# 该字段在添加后的字段名field_title="注册信息",# 该字段的标题field_doc="用户在网站上注册时所填写的信息",# 该字段的详细说明types=[EmailLogin,PhoneLogin],# 该字段可以接受的类型，此处为两种不同的登录方式discriminator="login_method",# 在子节点中，通过discriminator字段来区分不同的类型)classAuthInfo(ConfigLeaf):# 当节点只有一个字段时，可以直接使用ConfigLeaf，并将唯一字段名设置为`root`...@set_title("用户系统")classUserSystem(ConfigNode):username:UserNamegender:Genderage:Ageauth_info:AuthInfo命令行生成配置文件当程序完成定义时，可以通过调用mock_cli和model_dump_yaml方法，能在命令行中操作后生成配置文件：UserSystem.mock_cli().model_dump_yaml(comment=True)命令行执行效果，如下图所示：程序拓展接口当程序完成定义时，可以通过调用get_api_router方法来启动后端服务开启标准化的应用程序接口，以下是一个简单的案例：importuvicornimportfastapiapp=fastapi.FastAPI()app.include_router(UserSystem.get_api_router("/"))uvicorn.run(app,host="127.0.0.1",port=8000,log_level="info")用户界面本系统包含一个配套的网页端用户界面，以上案例对应的页面如下图所示：当点击表单字段前方的?标识时，会出现该字段的详细说明，如下图所示：当选择多类型字段的值后，其子节点的内容也会随之发生变化，如下图所示：当必填字段没有填写时，网页会给出提示：当已填字段未通过校验时，网页会给出提示：在验证通过时，可以生成 yaml 格式的配置文件，如下图所示：程序接口本系统的核心部分就是其配置节点（ConfigNode）和配置叶子节点（ConfigLeaf），它们共同构成了配置的树形结构。节点类（ConfigNode）节点类是pydantic.BaseModel的超集。作为配置系统的核心，用于构建、验证、转换、序列化配置树的结构。验证YAML文件使用model_validate_yaml方法，开发人员可以通过传递YAML文件的路径进行验证。如果验证成功，将返回一个有效的ConfigNode实例。模拟方法ConfigNode类还提供了多个模拟方法，如mock，mock_with_default，mock_with_blank和mock_cli。这些方法可以根据字段类型和默认值生成模拟实例。YAML序列化使用model_dump_yaml方法，可以将ConfigNode实例转储为YAML字符串。model_dump_mock_yaml方法提供了模拟实例的转储功能。生成后端接口路由get_api_router方法可用于获取API路由。约束验证verify_constraints方法用于验证约束条件，可以根据需要覆盖。叶节点类（ConfigLeaf）叶节点类继承自根模型和节点类，用于构建配置树的末端节点。装饰器设置标题（set_title）通过传递标题字符串，可以设置模型的标题。@set_title("标题")classExampleModel(ConfigNode):...设置说明（set_doc）该装饰器用于设置模型的详细说明。@set_doc("这是一个示例模型")classExampleModel(ConfigNode):...设置鉴别字段（set_discriminator）此装饰器可以设置模型的区分器字段名。@set_discriminator("type")classExampleModel(ConfigNode):...添加复合类型字段（add_union_field）此装饰器可以将具有多种类型的字段添加到模型中，还可以通过可选参数设置字段标题和文档。@add_union_field("field_name",[Type1,Type2])classExampleModel(ConfigNode):...